karakays
karakays

Reputation: 3673

Java Generics: Comparing an Integer to a Double

Can anyone help me compare an Integer to a Double using generics?

This is what I have:

public static <T extends Comparable<? super T>> int compare(T arg1, T arg2)
{
    return arg1.compareTo(arg2);
}

public static void main(String[] args)
{   
    Number i = new Integer(5);
    Number j = new Double(7);

    System.out.println(GenericsTest.compare(i, j));
}

The error message I get is: Bound mismatch: The generic method compare(T, T) of type GenericsTest is not applicable for the arguments (Number, Number). The inferred type Number is not a valid substitute for the bounded parameter >

Upvotes: 4

Views: 6544

Answers (5)

SkyWalker
SkyWalker

Reputation: 14309

The idea of this solution is to widen to BigDecimal and then compare the two numbers (now is cleaner but somehow formatting doesn't work). Note you may reuse this static comparator without having to cast to double anywhere else. In the implementation you do need conversion to double not to lose information, basically you widen to the most general representation.

private static final Comparator<Number> NUMBER_COMPARATOR = new Comparator<Number>() {
    private BigDecimal createBigDecimal(Number value) {
        BigDecimal result = null;
        if (value instanceof Short) {
            result = BigDecimal.valueOf(value.shortValue());
        } else 
        if (value instanceof Long) {
            result = BigDecimal.valueOf(value.longValue());             
        } else 
        if (value instanceof Float) {
            result = BigDecimal.valueOf(value.floatValue());                                
        } else 
        if (value instanceof Double) {
            result = BigDecimal.valueOf(value.doubleValue());                               
        } else 
        if (value instanceof Integer) {
            result = BigDecimal.valueOf(value.intValue());                              
        } else {
            throw new IllegalArgumentException("unsupported Number subtype: " + value.getClass().getName());
        }
                       assert(result != null);

        return result;
    }

    public int compare(Number o1, Number o2) {
        return createBigDecimal(o1).compareTo(createBigDecimal(o2));
    };
};

public static void main(String[] args) {
    Number i = Integer.valueOf(5);
    Number j = Double.valueOf(7);
              // -1
    System.out.println(NUMBER_COMPARATOR.compare(i, j));

         i = Long.MAX_VALUE;
         j = Long.valueOf(7);
              // +1
         System.out.println(NUMBER_COMPARATOR.compare(i, j));

         i = Long.MAX_VALUE;
         j = Long.valueOf(-7);
              // +1
         System.out.println(NUMBER_COMPARATOR.compare(i, j));

         i = Long.MAX_VALUE;
         j = Double.MAX_VALUE;
              // -1
         System.out.println(NUMBER_COMPARATOR.compare(i, j));

    i = Long.MAX_VALUE;
    j = Long.valueOf(Long.MAX_VALUE - 1);
    // +1
    System.out.println(NUMBER_COMPARATOR.compare(i, j));

              // sorting Long values
    Long[] values = new Long[] {Long.valueOf(10), Long.valueOf(-1), Long.valueOf(4)};
    Arrays.sort(values, NUMBER_COMPARATOR);
              // [-1, 4, 10] 
    System.out.println(Arrays.toString(values));  
}

Upvotes: 6

张焱伟
张焱伟

Reputation: 61

private boolean compareObject(Object expected, Object actual) {
    if (expected instanceof Number && actual instanceof Number) {
        double e = ((Number) expected).doubleValue();
        double a = ((Number) actual).doubleValue();
        return e == a;
    } else {
        return com.google.common.base.Objects.equal(expected, actual);
    }
}

Upvotes: 0

RokL
RokL

Reputation: 2812

Create a class that implements Comparable which takes a Number in the constructor. e.g.

public class GenericNumber implements Comparable<GenericNumber> {
    private Number num;
    public GenericNumber(Number num) {
        this.num = num;
    }
    // write compare function that compares num member of two
    // GenericNumber instances
}

Then simply do this:

GenericNumber i = new GenericNumber(new Integer(5));
GenericNumber j = new GenericNumber(new Double(7));
System.out.println(GenericsTest.compare(i,j));

Upvotes: -1

Bohemian
Bohemian

Reputation: 424993

Number doesn't implement Comparable.

Declare both variables as Integer.

Upvotes: 1

Frank
Frank

Reputation: 15641

As aready said in the comments, Number does not implement Comparable. But Double and Integer do.

One way to make this work is like this:

public static <T extends Comparable<? super T>> int compare(T arg1, T arg2)
{
    return arg1.compareTo(arg2);
}

public static void main(String[] args)
{   
    Double i = new Integer(5).doubleValue();
    Double j = new Double(7);

    System.out.println(GenericsTest.compare(i, j));
}

Upvotes: 1

Related Questions