16

I want to make a generic method which makes the total sum of a List of numbers.

What I was trying is this:

public static <T extends Number> T sumList(List<T> data)
{
    T total = 0;
    for (T elem : data)
    {
        total += elem;
    }
    return total;
}

But the problem is that there is no += operator in T and that total can't be assigned to zero.

How can I do this?

Thanks

2
  • @Cris,Martijn:Can you guy's point to a sample code which does the above task.I've lost touch with c++.I just want to see how it will be done in c++. Commented Oct 3, 2010 at 19:23
  • FWIW, other JVM languges make this pretty straightforward, too: in Clojure: "(reduce + '(1 2.0 3))", and in scala: "List(1, 2.0, 3).sum" Commented Oct 5, 2010 at 18:26

4 Answers 4

20

There are ways you can hack this together but in all honestly, generics is simply not the way to go here. Build a method for each concrete primitive wrapper type and implement them separately. It'll be way too much of a headache to make it generic; arithmetic operations can't happen generically.

You don't really gain anything by making it generic, either. It's such simple and constant code that you aren't worried about code duplication, since it's not going to change. And people aren't going to be passing in their own type of Number to your code; the domain of types it applies to is already well defined and finite.

Sign up to request clarification or add additional context in comments.

1 Comment

It hurts that this is true, but it is (+1)
4

I've done that recently (based on lambdaj code) beware it will need all your elements to be the same type (you can't really add a Byte and a BigDecimal) and can throw a CCE if it isn't the case and won't handle custom Number:

public class SumAggregator<T extends Number> {
    public T aggregate(Iterable<T> iterable) {
        T result = null;
        for (T item : iterable) {
            result = aggregate(result, item);
        }
        return result;
    }


    @SuppressWarnings("unchecked")
    protected T aggregate(T first, T second) {
        if (first == null) {
            return second;
        } else if (second == null) {
            return first;
        } else if (first instanceof BigDecimal) {
            return (T) aggregate((BigDecimal) first, (BigDecimal) second);
        } else if (second instanceof BigInteger) {
            return (T) aggregate((BigInteger) first, (BigInteger) second);
        } else if (first instanceof Byte) {
            return (T) aggregate((Byte) first, (Byte) second);
        } else if (first instanceof Double) {
            return (T) aggregate((Double) first, (Double) second);
        } else if (first instanceof Float) {
            return (T) aggregate((Float) first, (Float) second);
        } else if (first instanceof Integer) {
            return (T) aggregate((Integer) first, (Integer) second);
        } else if (first instanceof Long) {
            return (T) aggregate((Long) first, (Long) second);
        } else if (first instanceof Short) {
            return (T) aggregate((Short) first, (Short) second);
        } else {
            throw new UnsupportedOperationException("SumAggregator only supports official subclasses of Number");
        }
    }

    private BigDecimal aggregate(BigDecimal first, BigDecimal second) {
        return first.add(second);
    }

    private BigInteger aggregate(BigInteger first, BigInteger second) {
        return first.add(second);
    }

    private Byte aggregate(Byte first, Byte second) {
        return (byte) (first + second);
    }

    private Double aggregate(Double first, Double second) {
        return first + second;
    }

    private Float aggregate(Float first, Float second) {
        return first + second;
    }

    private Integer aggregate(Integer first, Integer second) {
        return first + second;
    }

    private Long aggregate(Long first, Long second) {
        return first + second;
    }

    private Short aggregate(Short first, Short second) {
        return (short) (first + second);
    }
}

This code executed on ideone with examples.

2 Comments

Thanks, Colin. But in my situation, I want to use short code. I will remember your post when I really need the generics. But I can do without.
@Martijn Courteaux, in my case, I couldn't do without generics, but if you can avoid generics and avoid to end up with this kind of code (which is IMO really heavy [tons of cast]) you should do without generics.
0

You can use a library, such as Generic Java Math (its numbers part), which provides generic operations for Number subclasses. It provides a way to work generically with numbers, just as in your example, but with passing Arithmetics object around, that does the actual calculation. See example on the home page.
It must use boxed types, so if you need speed, no generic implementation can do that in Java, you must use primitive types.

Comments

0

Have a look at following example of generic method for summation of any Number type of variable lists... I am sure that this is what you was asking for..

Mark Peters is also right in his answer, but this also is a solution to go for.

public class GenericSum {
@SuppressWarnings("unchecked")
public static <E> E sumArray(E[] inputArray) {
    Double result = 0.0;
    // Sum array elements
    for (E element : inputArray) {
        result = ((Number) result).doubleValue()
                + ((Number) element).doubleValue();
    }
    return ((E) result);
}

public static void main(String args[]) {
    // Create arrays of Integer, Double
    Integer[] intArray = { 1, 2, 3, 4, 5 };
    Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };

    System.out.println("Sum of doubles : " + sumArray(intArray));
    System.out.println("Sum of doubles : " + sumArray(doubleArray));
}

}

1 Comment

this converts everything to double, which is kinda not the point

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.