Question

I currently have a method to return the non-zero indices in an iterable. I want this method to be able to handle any class extending java.lang.Number. Number, of course, does not implement Comparable. But I don't want to have separate methods for Long, Integer, etc. As of now, this is what I have:

public static <T extends Number & Comparable<? super T>> nonZeroIndices(Iterable<T> iterable) {
    Set<Integer> nonzero_indices = Sets.newTreeSet();
    Iterator<T> iterator = iterable.iterator();
    int i = 0;
    while (iterator.hasNext()) {
        T t = iterator.next();
        if (t.doubleValue() != 0) // This is what is bothering me
            nonzero_indices.add(i);
        i++;
    }
    return nonzero_indices;
}

But I want to avoid doubleValue(). I would also like to avoid having a bunch instanceOf calls in my method. Can I make this method to work on type T where T extends Number and T implements Comparable?

EDIT Using <T extends Number & Comparable<? super T>> (as suggested by Sotirios) will still require a bunch of instanceOf statements, which I want to avoid. I was hoping that I can safely cast zero to type T, but the compiler issues a warning saying "unchecked cast".

To be more specific, I tried

if (t.compareTo((T) new Integer(0) == 0)

but it issues the warning.

Was it helpful?

Solution

The problem is that Integer is specifically Comparable<Integer>, Double is specifically Comparable<Double>, and so on, so to use their compareTo, you have to pass in a reference of the appropriate type, which means that you have to have an object of the appropriate type. Note that the cast in (Double) new Integer(0) will never succeed, because you can't have a reference of one type that points to an object of an incompatible type. (And actually it's a compile error, because the compiler can tell in this case that the cast will never succeed.)

I think your doubleValue approach is probably the best one.

OTHER TIPS

It is not possible with the Number hierarchy. You have to use instanceof.

In general, your doubleValue trick seems to work most of the time. I could construct a false positive with BigDecimal:

new BigDecimal("0.000..<repeats 380 times>..001").doubleValue() == 0

If that is a problem for you, you might want to add a special case for BigDecimal.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top