如何将 Map 中的值与流相加?

2022-01-22 00:00:00 java-8 java generics java-stream

我想要一个流的等价物:

I want the equivalent of this with a stream:

public static <T extends Number> T getSum(final Map<String, T> data) {
    T sum = 0;
    for (String key: data.keySet())
        sum += data.get(key);
    return sum;
}

这段代码实际上并没有编译,因为 0 不能分配给类型 T,但你明白了.

This code doesn't actually compile because 0 cannot be assigned to type T, but you get the idea.

推荐答案

这是另一种方法:

int sum = data.values().stream().reduce(0, Integer::sum);

(不过,对于 int 的总和,Paul 的回答减少了装箱和拆箱.)

(For a sum to just int, however, Paul's answer does less boxing and unboxing.)

至于这样做一般,我不认为有更方便的方法.

As for doing this generically, I don't think there's a way that's much more convenient.

我们可以这样做:

static <T> T sum(Map<?, T> m, BinaryOperator<T> summer) {
    return m.values().stream().reduce(summer).get();
}

int sum = MyMath.sum(data, Integer::sum);

但你总是会度过夏天.reduce 也有问题,因为它返回 Optional.上面的 sum 方法对空映射抛出异常,但是空的 sum 应该是 0.当然,我们也可以传递 0:

But you always end up passing the summer. reduce is also problematic because it returns Optional. The above sum method throws an exception for an empty map, but an empty sum should be 0. Of course, we could pass the 0 too:

static <T> T sum(Map<?, T> m, T identity, BinaryOperator<T> summer) {
    return m.values().stream().reduce(identity, summer);
}

int sum = MyMath.sum(data, 0, Integer::sum);

相关文章