在对象流中对每个字段求和

时间:2016-08-22 15:51:12

标签: java java-8 java-stream

我想创建对象MyObject的实例,其中每个字段都是该字段值的总和

我创建了一个对象

       public class MyObject{
           int value;
           double length;
           float temperature;

           MyObject(int value, double length, float temperature){
               this.value = value;
               this.length = length
               this.temperature = temperature
           }
        }

然后我构建对象列表:

    List<MyObject> list = new ArrayList<MyObject>{{
          add(new MyObject(1, 1d, 1.0f));
          add(new MyObject(2, 2d, 2.0f));
          add(new MyObject(3, 3d, 3.0f));
    }}

我想要创建对象(new MyObject(6, 6d, 6f)

每个流总结一个字段很容易:

Integer totalValue = myObjects.parallelStream().mapToInt(myObject -> myObject.getValue()).sum(); //returns 6;

Double totalLength = myObjects.parallelStream().mapToDouble(MyObject::getLength).sum(); //returns 6d

然后构造对象new MyObject(totalValue, totalLength, totalTemperature);

但是我可以在一个流中汇总所有字段吗? 我想要流回来

new MyObject(6, 6d, 6.0f)

3 个答案:

答案 0 :(得分:3)

您可以尝试以下内容

MyObject me = new MyObject(
    list.stream().mapToInt(MyObject::getValue).sum(),
    list.stream().mapToDouble(MyObject::getLength).sum(),
    (float)list.stream().mapToDouble(MyObject::getTemperature).sum());

这将满足您的需求。您也可以使用Stream.reduce来做同样的事情。

答案 1 :(得分:2)

其他解决方案是有效的,但它们都会产生不必要的开销;一个通过多次复制MyObject,另一个通过多次流式传输集合。如果MyObject是可变的,那么使用collect()的理想解决方案是mutable reduction

// This is used as both the accumulator and combiner,
// since MyObject is both the element type and result type
BiConsumer<MyObject, MyObject> reducer = (o1, o2) -> {
    o1.setValue(o1.getValue() + o2.getValue());
    o1.setLength(o1.getLength() + o2.getLength());
    o1.setTemperature(o1.getTemperature() + o2.getTemperature());
}
MyObject totals = list.stream()
        .collect(() -> new MyObject(0, 0d, 0f), reducer, reducer);

此解决方案仅创建一个额外的MyObject实例,并且只迭代列表一次。

答案 2 :(得分:1)

它是reduce方法的直接应用程序:

Stream.of(new MyObject(1, 1d, 1.0f), new MyObject(2, 2d, 2.0f), new MyObject(3, 3d, 3.0f)).
                reduce((a, b) -> new MyObject(a.value + b.value, a.length + b.length, a.temperature + b.temperature))