是否有可能编写一个方法total来对a的所有元素求和,或者ArrayList它是什么类型的?<Integer><Long>
我不能写
public long total(ArrayList<Integer> list)
Run Code Online (Sandbox Code Playgroud)
和
public long total(ArrayList<Long> list)
Run Code Online (Sandbox Code Playgroud)
一起因为擦除错误,并Integer不会自动延伸到Long反之亦然......但内部的代码是相同的!
Lii*_*Lii 11
是的,你可以实现这样的方法,因为这两个Integer和Long延伸Number.例如,您可以使用通配符类型作为列表元素类型:
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;
}
Run Code Online (Sandbox Code Playgroud)
这仅适用于整数类型,因为sum变量和返回值属于类型long.
理想情况下,您希望能够使用带有Floats和Doubles 的方法并返回与列表元素类型相同类型的对象,但这有两个原因并不容易:
Number就是将其值作为原始数字类型之一.你不能以数量依赖的方式对它们中的两个进行求和.编辑: 很久以后......
只是为了好玩,让我们以一种很好的方式为Java做到这一点.您需要做的是手动提供上面提到的两个操作.在代数和函数编程的上下文中,一种具有两个这样的操作的值通常被称为monoid.
可以通过创建表示monoid操作的对象来解决问题:
interface MonoidOps<T> {
T id();
T op(T o1, T o2);
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
为了提供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);
}
}
Run Code Online (Sandbox Code Playgroud)
这些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);
Run Code Online (Sandbox Code Playgroud)
这个total方法会像这样调用:
int sum = total(Arrays.asList(1, 2, 3), INT_MONOID_OPS);
Run Code Online (Sandbox Code Playgroud)