在java 8中使用流API,如何从Map返回实例,需要多次计算

Joh*_*ohn 4 java lambda java-8 java-stream

假设有这样的类:

class A {

    long sent;
    long received;
    double val; // given as max {(double)sent/someDenominator,(double)received/someDenominator}
}
Run Code Online (Sandbox Code Playgroud)

其中有多个实例引用Map<String , A>.

是否可以一次性使用流API返回具有以下属性的A类实例:

  • sent =来自所有实例的已发送字段的总和
  • received =来自Map中所有实例的已接收字段的总和
  • val = val的最大值,给定val = max {sent/someDenominator,received/someDenominator}的所有条目

使用标准循环和一次迭代会有什么琐碎的任务,我不知道如何用流API实现.

Ale*_* C. 7

你可以使用reduce:

Optional<A> a = map.values()
                   .stream()
                   .reduce((a1, a2) -> new A(a1.sent + a2.sent, a1.received + a2.received, Math.max(a1.val, a2.val)));
Run Code Online (Sandbox Code Playgroud)


Tag*_*eev 5

如果您的A对象是可变的,则可以基于collect()方法实现更有效的解决方案.添加A描述合并策略的方法:

class A {
    long sent;
    long received;
    double val;

    void merge(A other) {
        sent += other.sent;
        received += other.received;
        val = Math.max(val, other.val);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以写了

A a = map.values().stream().collect(A::new, A::merge, A::merge);
Run Code Online (Sandbox Code Playgroud)

这样您就不必A为每个缩减步骤创建中间对象:将重用单个公共对象.

  • 这非常有用.我只想到如何跳过中间对象创建. (3认同)