是否可以编写单个方法total
来对ArrayList
的所有元素求和,其类型为<Integer>
或<Long>
?
我不能只写
public long total(ArrayList<Integer> list)
和
public long total(ArrayList<Long> list)
因为擦除错误,Integer
不会自动扩展到Long
,反之亦然......但内部代码完全相同!
答案 0 :(得分:11)
是的,您可以实施此类方法,因为Integer
和Long
都会延伸Number
。例如,您可以使用wildcard type作为列表元素类型:
public static long total(List<? extends Number> list) {
long sum = 0;
for (Number n : list) {
if (!(n instanceof Byte || n instanceof Short || n instanceof Integer || n instanceof Long)) {
throw new IllegalArgumentException();
}
sum += n.longValue();
}
return sum;
}
这仅适用于整数类型,因为sum
变量和返回值的类型为long
。
理想情况下,您希望能够将此方法与Float
和Double
一起使用,并返回与列表元素类型相同类型的对象,但这并不容易有两个原因:
Number
唯一能做的就是将其值作为原始数字类型之一。你不能以数量依赖的方式对它们中的两个进行求和。编辑: 很久以后......
只是为了好玩,让我们以一种很好的方式为Java做这件事。您需要做的是手动提供上面提到的两个操作。在代数和函数式编程的上下文中,一种具有两个这样的操作的值通常称为monoid。
可以通过创建表示幺半群操作的对象来解决问题:
interface MonoidOps<T> {
T id();
T op(T o1, T o2);
}
现在可以实现total
方法,除了列表之外还可以使用此类型的对象:
public static <T> T total(List<T> list, MonoidOps<T> ops) {
T sum = ops.id();
for (T e : list) {
sum = ops.op(e, sum);
}
return sum;
}
为数字类提供MonoidOps
实现,让我们创建一个简单的帮助类:
class SimpleMonoidOps<T> implements MonoidOps<T> {
private final T idElem;
private final BinaryOperator<T> operation;
public SimpleMonoidOps(T idElem, BinaryOperator<T> operation) {
this.idElem = idElem;
this.operation = operation;
}
public T id() {
return idElem;
}
public T op(T o1, T o2) {
return operation.apply(o1, o2);
}
}
MonoidOps
实现现在可以像这样整洁地编写:
static final MonoidOps<Integer> INT_MONOID_OPS = new SimpleMonoidOps<>(0, Integer::sum);
static final MonoidOps<Double> DOUBLE_MONOID_OPS = new SimpleMonoidOps<>(0.0, Double::sum);
total
方法会像这样调用:
int sum = total(Arrays.asList(1, 2, 3), INT_MONOID_OPS);
答案 1 :(得分:1)
您还可以在Java 8中使用流
public static <T extends Number> long sumList(List<T> list)
{
return list.stream().mapToLong(a -> a.longValue()).sum();
}
答案 2 :(得分:0)
您可以将Java的泛型用于此
public <T extends Number> T total(List<T> list) {
T sum = 0;
for (T n : list) {
sum += n.longValue();
}
return sum;
}
知道T
永远是Number
,事情就会简化。但是,如果需要,此解决方案也可以用于String
。唯一的变化是extends
部分。