Java: общие методы и номера
Я хочу создать общий метод, который делает общую сумму чисел List
.
Я пытаюсь это сделать:
public static <T extends Number> T sumList(List<T> data)
{
T total = 0;
for (T elem : data)
{
total += elem;
}
return total;
}
Но проблема в том, что there is no += operator in T
и что total can't be assigned to zero
.
Как я могу это сделать?
Спасибо
Ответы
Ответ 1
Есть способы, которыми вы можете взломать это вместе, но, честно говоря, дженерики - это просто не путь сюда. Создайте метод для каждого конкретного примитивного типа оболочки и реализуйте их отдельно. Это будет слишком большая головная боль, чтобы сделать ее общей; арифметические операции не могут произойти в общем случае.
Вы действительно ничего не получаете, сделав его общим. Это такой простой и постоянный код, что вас не беспокоит дублирование кода, поскольку оно не изменится. И люди не собираются передавать свой тип номера в ваш код; область типов, к которой она относится, уже хорошо определена и конечна.
Ответ 2
Я сделал это недавно (на основе lambdaj), остерегайтесь, что все ваши элементы будут одинаковыми (вы не может действительно добавить Byte
и BigDecimal
) и может выбросить CCE, если это не так, и не будет обрабатывать пользовательские 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);
}
}
Этот код выполнен на ideone с примерами.
Ответ 3
Вы можете использовать библиотеку, такую как Generic Java Math (ее часть номера), которая предоставляет общие операции для подклассов Number. Он обеспечивает способ работы в целом с числами, как и в вашем примере, но с передачей объекта Arithmetics вокруг, что делает фактический расчет. См. Пример на домашней странице.
Он должен использовать типы в штучной упаковке, поэтому, если вам нужна скорость, никакая общая реализация не может сделать это на Java, вы должны использовать примитивные типы.
Ответ 4
Взгляните на следующий пример универсального метода суммирования любого типа переменных списка переменных...
Я уверен, что это то, о чем вы просили.
Марк Петерс также прав в своем ответе, но это также решение для решения.
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));
}
}