Search code examples
javalistgenericscollectionsarray-difference

Arithmetic element by element difference between 2 collections using Java Generics


Say we got 2 ordered collections of numbers. We want to compute the arithmetic difference element by element. I think we need to use List of Number in order to model the idea of 'ordered collection of numbers'. The problem is that the arithmetic difference (a banal '-' like in 3-2) is not defined for Number. I can cast everything to Double, but I'd rather prefer a clean solution.

public static <E extends Number> List<E> listDifferenceElementByElement(List<E> minuend, List<E> subtrahend) throws Exception {
    if (minuend.size() != subtrahend.size()) {
        throw new Exception("Collections must have the same size"); //TODO: better exception handling
    }
    List<E> difference = new ArrayList<E>();
    int i = 0;
    for (E currMinuend : minuend) {
        difference.add(currMinuend-subtrahend.get(i)); //error: The operator - is undefined for the argument type(s) E, E
        i++;
    }
    return difference;
}

Any idea?


Solution

  • Since Number does not provide any subtract method, you can't do it simply. The alternatives I can think of are:

    1. use the provided doubleValue() method, and return a double, but you could lose precision if the lists contain BigDecimal for example.
    2. have one method per available Number subclass, but it could create a lot of duplicated code...
    3. restrict the type to whatever makes sense (say double if precision does not matter too much or BigDecimal if it does), which is a subcase of (2).

    Option 2 could be implemented like by replacing difference.add(currMinuend-subtrahend.get(i)); by difference.add(subtract(currMinuend, subtrahend.get(i)));

    Then it's only a matter of writing 10 subtract methods:

    private static int subtract(int a, int b) { return a - b; }
    private static double subtract(double a, double b) { return a - b; }
    private static BigDecimal subtract(BigDecimal a, BigDecimal b) { return a.subtract(b); }
    

    etc.