【问题标题】:Sum each field in stream of objects对对象流中的每个字段求和
【发布时间】:2016-12-29 06:11:50
【问题描述】:

我想创建对象 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)

【问题讨论】:

    标签: java java-8 java-stream


    【解决方案1】:

    其他解决方案是有效的,但它们都会产生不必要的开销;一种是多次复制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】:

      直接申请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))
      

      【讨论】:

        【解决方案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 来做同样的事情。

        【讨论】:

        • reduce 的版本相比,这避免了创建中间MyObject 实例。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-14
        • 2014-05-31
        相关资源
        最近更新 更多