在使用流API的Java8中,如何从映射返回实例并进行多个计算

在使用流API的Java8中,如何从映射返回实例并进行多个计算,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,假设有这样的类: class A { long sent; long received; double val; // given as max {(double)sent/someDenominator,(double)received/someDenominator} } 其中,Map中有大量实例引用 是否可以使用流API一次性返回具有以下属性的类A实例: sent=来自所有实例的已发送字段的总和 received=从映射中的所有实例接收的字段的总和 val=v

假设有这样的类:

class A {

    long sent;
    long received;
    double val; // given as max {(double)sent/someDenominator,(double)received/someDenominator}
}
其中,
Map
中有大量实例引用

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

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

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

您可以使用
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)));
可选a=map.values()
.stream()
.reduce((a1,a2)->新A(a1.sent+a2.sent,a1.received+a2.received,Math.max(a1.val,a2.val));

如果您的
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);
    }
}
现在你可以写作了

A a = map.values().stream().collect(A::new, A::merge, A::merge);

这样,您就不必为每个缩减步骤创建一个中间
对象:而是重用一个公共对象。

需要解释吗?我不会愤怒地否决你的投票……如果是两个
值的最大值,为什么
val
a
double
?还是我误解了?我忘了包括val是通过除以某个值(从键名派生)来计算的。听起来你想创建一个自定义值。这真的很有用。我正在考虑如何跳过中间对象的创建。