减少java中自定义对象的操作

时间:2018-05-29 10:48:20

标签: java java-8 java-stream

如何使用Reduce操作在对象的两个字段上执行求和。

e.g。

class Pojo
{
    public Pojo(int a, int b) {
        super();
        this.a = a;
        this.b = b;
    }
    int a ;
    int b;
    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
    public int getB() {
        return b;
    }
    public void setB(int b) {
        this.b = b;
    }

}

Pojo object1 = new Pojo(1, 1);
Pojo object2 = new Pojo(2, 2);
Pojo object3 = new Pojo(3, 3);
Pojo object4 = new Pojo(4, 4);

List<Pojo> pojoList = new ArrayList<>();

pojoList.add(object1);
pojoList.add(object2);
pojoList.add(object3);
pojoList.add(object4);

我可以使用IntStream执行求和:

int sum = pojoList.stream()
                  .mapToInt(ob -> (ob.getA() + ob.getB()))
                  .sum();

我想使用reduce 执行相同的操作,但不知怎的,我的语法不正确:

pojoList.stream()
        .reduce(0, (myObject1, myObject2) -> (myObject1.getA() + myObject2.getB()));

5 个答案:

答案 0 :(得分:12)

好吧,如果你想在IntStream上调用reduce:

int sum = pojoList.stream()
                  .mapToInt(ob ->(ob.getA()+ob.getB()))
                  .reduce(0, (a,b)->a+b);

当然,同样适用于Stream<Integer>

int sum = pojoList.stream()
                  .map(ob ->(ob.getA()+ob.getB()))
                  .reduce(0, (a,b)->a+b);

或使用方法参考:

int sum = pojoList.stream()
                  .map(ob ->(ob.getA()+ob.getB()))
                  .reduce(0, Integer::sum);

或没有map()

int sum = pojoList.stream()
                  .reduce(0, (s,ob)->s+ob.getA()+ob.getB(),Integer::sum);

在最后一个例子中,我使用了变体:

<U> U reduce(U identity,
             BiFunction<U, ? super T, U> accumulator,
             BinaryOperator<U> combiner);

因为减少的值(Integer)与Stream元素的类型不同。

第一个参数是标识值 - 0。

第二个参数将当前getA()元素的getB()Pojo值添加到中间总和。

第三个参数组合了两个部分和。

答案 1 :(得分:4)

sum()方法实现如下:

public final int sum() {
    return reduce(0, Integer::sum);
}

sum()替换reduce()

int sum = pojoList.stream()
                  .mapToInt(ob -> (ob.getA() + ob.getB()))
                  .reduce(0, Integer::sum);

或者,没有mapToInt()

int pojoSum = pojoList.stream()
                      .reduce(0, (sum, ob) -> sum + ob.getA() + ob.getB(), Integer::sum);

有关详情,请参阅Reduction operations段。

答案 2 :(得分:2)

几乎与伊兰的答案相同:

int sum = pojoList.stream()
                  .mapToInt(ob ->(ob.getA()+ob.getB()))
                  .reduce(Integer::sum)
                  .orElse(0);

只是为了它的乐趣,你也可以使用collect

int result = pojoList.stream()
            .collect(
                    () -> new int[] { 0 },
                    (x, y) -> x[0] = x[0] + y.getA() + y.getB(),
                    (left, right) -> left[0] += right[0])[0];

答案 3 :(得分:2)

reduce function you are using正在使用BinaryOperator,它将两个T对象作为参数,返回一个T对象

你想要的是这个reduce function,它与累加器一起使用,以下是如何使用它(参见Eran的回答):

<script>
    var canvas = null;
    var context = null;
    var imageObj = null;

    window.onload = function(){
        canvas = document.getElementById('canvas');
        context = canvas.getContext('2d');
        imageObj = new Image();

        var image = '<?php echo $filepath; ?>';
        imageObj.src = image;
        context.drawImage(imageObj, 0, 0);

        draw();
    }

    function draw() {
        ctx = canvas.getContext('2d');
        ctx.fillStyle = "black";

        for(var i = 0; i < 2; i++) {
            var x = Math.random()*400;
            var y = Math.random()*300;
            ctx.beginPath();
            ctx.arc(x , y, 2, 0, 2 * Math.PI, false);
            ctx.fill();
            ctx.stroke();
            ctx.closePath();
        }
    }
</script>

答案 4 :(得分:2)

class Pojo {
  static public Pojo add(Pojo p1, Pojo p2) {
    return new Pojo(p1.getA() + p2.getA(), p1.getB() + p2.getB())
  }
  //...
}

所以稍后:

Pojo pojoSum = pojoList.stream().reduce(new Pojo(0,0), Pojo::add);
pojoSum.getA() + pojoSum.getB()