I would like to generically add numbers in java. I\'m running into difficulty because the Numbers class doesn\'t really support what I want to do. What I\'ve tried so far
Number doesn't support any operations so you need to cast the values to the types required. e.g. If Number is a BigDecimal, there is no +=
operator.
below method get numbers such as int, float, etc and calculate sum of them.
@SafeVarargs
private static <T extends Number> double sum(T... args) {
double sum = 0d;
for (T t : args) {
sum += t.doubleValue();
}
return sum;
}
You should check runtime type (e.g. using instanceof
) and cast to the known type and do appropriate addition operation. Not sure what will be type of result, taking in account that the list could contain a lot of different number types.
Number has intValue(), floatValue(), doubleValue(), longValue, and shortValue(). Choose one and use it. For example,
double total;
total += number.doubleValue();
return total;
Also, java generics are in no way equivalent to c++ templates. You can not allocate new instances of a java generic type. This can never work:
E hoot = (E) new Object();
Finally, long
, short
, int
, double
, and float
are not class types; they are primitive types. As such they are not available for use with Java generics.
since the introduction of Java 8 streams and lambda you can have a shorter solution
public interface Adder {
static <E extends Number> E sumValues(Collection<E> objectsToSum, BinaryOperator<E> sumOp) {
return objectsToSum.stream().reduce(sumOp).orElse(null);
}
}
and use it as follows
int sum = Adder.sumValues(List.of(4, 5, 6, 7), Integer::sum);
Note, that Stream::reduce
with just accumulator returns Optional
that's why I used orElse(null)
, but I would recommend to send also zero value as parameter to Adder::sumValue
In order to calculate a sum generically, you need to provide two actions:
In Java, you do it through an interface. Here is a complete example:
import java.util.*;
interface adder<T extends Number> {
T zero(); // Adding zero items
T add(T lhs, T rhs); // Adding two items
}
class CalcSum<T extends Number> {
// This is your method; it takes an adder now
public T sumValue(List<T> list, adder<T> adder) {
T total = adder.zero();
for (T n : list){
total = adder.add(total, n);
}
return total;
}
}
public class sum {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(4);
list.add(8);
CalcSum<Integer> calc = new CalcSum<Integer>();
// This is how you supply an implementation for integers
// through an anonymous implementation of an interface:
Integer total = calc.sumValue(list, new adder<Integer>() {
public Integer add(Integer a, Integer b) {
return a+b;
}
public Integer zero() {
return 0;
}
});
System.out.println(total);
}
}