Comparing the Values of Two Generic Numbers

Comparing the values of two generic Numbers

A working (but brittle) solution is something like this:

class NumberComparator implements Comparator<Number> {

public int compare(Number a, Number b){
return new BigDecimal(a.toString()).compareTo(new BigDecimal(b.toString()));
}

}

It's still not great, though, since it counts on toString returning a value parsable by BigDecimal (which the standard Java Number classes do, but which the Number contract doesn't demand).

Edit, seven years later: As pointed out in the comments, there are (at least?) three special cases toString can produce that you need to take into regard:

  • Infinity, which is greater than everything, except itself to which it is equal
  • -Infinity, which is less than everything, except itself to which it is equal
  • NaN, which is extremely hairy/impossible to compare since all comparisons with NaN result in false, including checking equality with itself.

Java how to compare two generic type parameters

The < and > operators can only be used with primitive types, and the Number class does not implement Comparable itself, so you can't use compareTo.

However if you add Comparable<T> as a type bound:

public class MyList<T extends Number & Comparable<T>> {
...
}

then you can use the compareTo method:

public T largest() {
boolean onFirstObj = true;
T largestVal = null;

for (T t : list) {
if (onFirstObj) {
largestVal = t;
onFirstObj = false;
} else {
if (t.compareTo(largestVal) > 0) {
largestVal = t;
}
}
}

return largestVal;
}

How do you compare two values of the same generic type in java?

When your code provides ambiguous methods like your two delete, the best solution is always to rename the method themselves. Instead of supprimer(Key, int), rename it to supprimerParIdx(Key, int).

You could also check the instance of your Object to make sure it's not an Integer :

if (element instanceof Integer) {
throw new RuntimeException("Integers are forbidden by my law!");
}

or instead of an Exception, unbox and call the other method

this(key, element.intValue());

This is, of course, dirty in everyway.

On a side note :

new Integer(23) : Never do this, use Integer.valueOf(23) instead, same goes for most Boxed primitives.

Compare two generic types in Java?

You can't do that because of type erasure, it is that simple.

Consider the following:

public static void main(String[] args) {
List<? extends Number> l1 = Arrays.asList(1L, 2, 3L);
List<? extends Number> l2 = Arrays.asList(1);
isEqual(l1, l2);
}

public static <U, V> boolean isEqual(List<U> a, List<V> b) {
// is U == V here?
}

Is U == V here? l1 contains Long and Integer instances but l2 contains a single Integer instance.


I'm guessing from your comment:

The first condition should be that their type are the same

that what you should have instead is a single type U. In this case, use the following signature:

public static <U> boolean isEqual(List<U> a, List<U> b) {

}

and with that, the above code won't compile anymore.


What you could also do is add 2 parameters accepting the classes:

public static <U, V> boolean isEqual(List<U> a, List<V> b, Class<U> uClass, Class<V> vClass) {
if (!uClass.equals(vClass)) {
// classes are different
}
}

In this case, you can print a message if the classes given are not the same.

c# compare two generic values

You cannot use operators on generic types (except for foo == null which is special cased) unless you add where T : class to indicate it is a reference type (then foo == bar is legal)

Use EqualityComparer<T>.Default to do it for you. This will not work on types which only supply an operator overload for == without also either:

  • implement IEquatable<T>
  • overrides object.Equals()

In general implementing the == operator and not also doing at least one of these would be a very bad idea anyway so this is not likely to be an issue.

public bool IsDataChanged<T>()
{
T value1 = GetValue2;
T value2 = GetValue1();

return !EqualityComparer<T>.Default.Equals(value1 , value2);
}

If you do not restrict to IEquatable<T> then the EqualityComparer default fallback may cause boxing when used with value types if they do not implement IEquatable<T> (if you control the types which are being used this may not matter). I am assuming you were using =! for performance though so restricting to the Generic type will avoid accidental boxing via the Object.Equals(object) route.

Comparing Two values in a generic method c#

You could use Comparer<T>.Default.Compare(operatorOne, operatorTwo) for comparation. Please be aware that if T does not implement IComparable and IComparable<T>, Comparer<T>.Default.Compare throws an exception.

To make sure that T implements IComparable, you may add where T: IComparable constraint. (It will exclude classes which implement IComparable<T>, but not IComparable. Still may be acceptable, since many classes which implement IComparable<T>, implement IComparable too.)

private bool Comparison<T>(T operatorOne, T operatorTwo, string operand)
where T: IComparable
{
switch(operand.ToLower())
{
case "=":
return Comparer<T>.Default.Compare(operatorOne, operatorTwo) == 0;
case "<":
return Comparer<T>.Default.Compare(operatorOne, operatorTwo) < 0;
case ">":
return Comparer<T>.Default.Compare(operatorOne, operatorTwo) > 0;
case "contains":
return operatorOne.ToString().Contains(operatorTwo.ToString());
default:
return false;
}
}

P.S.

As Servy suggested, you may also pass IComparer as an extra parameter to the function. It would allow to cover types which implement neither IComparable nor IComparable<T>, so Comparer<T>.Default does not work for them.

Also, credits go to @TimothyShields, who suggested Comparer<T>.Default.



Related Topics



Leave a reply



Submit