不同类型的ArrayList的总和

Iva*_*van 4 java arraylist

是否有可能编写一个方法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

是的,你可以实现这样的方法,因为这两个IntegerLong延伸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 的方法并返回与列表元素类型相同类型的对象,但这有两个原因并不容易:

  1. 你唯一可以做的Number就是将其值作为原始数字类型之一.你不能以数量依赖的方式对它们中的两个进行求和.
  2. 无法创建正确类的0对象.

编辑: 很久以后......

只是为了好玩,让我们以一种很好的方式为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)