How to use Reduce operation for performing sum on two fields of an object.
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);
I can perform sum using IntStream
like this:
int sum = pojoList.stream()
.mapToInt(ob -> (ob.getA() + ob.getB()))
.sum();
I want to perform the same operation using reduce, but somehow I am not getting the syntax correct:
pojoList.stream()
.reduce(0, (myObject1, myObject2) -> (myObject1.getA() + myObject2.getB()));
Reducing is the repeated process of combining all elements. reduce operation applies a binary operator to each element in the stream where the first argument to the operator is the return value of the previous application and second argument is the current stream element.
A reduction is a terminal operation that aggregates a stream into a type or a primitive. The Java 8 Stream API contains a set of predefined reduction operations, such as average , sum , min , max , and count , which return one value by combining the elements of a stream.
In Java, reducing is a terminal operation that aggregates a stream into a type or a primitive type. Java 8 provides Stream API contains set of predefined reduction operations such as average(), sum(), min(), max(), and count(). These operations return a value by combining the elements of a stream.
Identity is the default result of reduction if there are no elements in the stream. That's the reason, this version of reduce method doesn't return Optional because it would at least return the identity element. Ignoring this rule will result in unexpected outcomes.
Well, if you want to call reduce on the IntStream
:
int sum = pojoList.stream()
.mapToInt(ob ->(ob.getA()+ob.getB()))
.reduce(0, (a,b)->a+b);
Of course, the same will work on a Stream<Integer>
:
int sum = pojoList.stream()
.map(ob ->(ob.getA()+ob.getB()))
.reduce(0, (a,b)->a+b);
or with a method reference:
int sum = pojoList.stream()
.map(ob ->(ob.getA()+ob.getB()))
.reduce(0, Integer::sum);
or without the map()
:
int sum = pojoList.stream()
.reduce(0, (s,ob)->s+ob.getA()+ob.getB(),Integer::sum);
In this last example, I use the variant:
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
since the reduced value (an Integer
) is different than the type of the Stream
elements.
The first parameter is an identity value - 0.
The second parameter adds the getA()
and getB()
values of the current Pojo
element to the intermediate sum.
The third parameter combines two partial sums.
sum()
method implementation is as follows:
public final int sum() {
return reduce(0, Integer::sum);
}
Replacing sum()
with reduce()
:
int sum = pojoList.stream()
.mapToInt(ob -> (ob.getA() + ob.getB()))
.reduce(0, Integer::sum);
Or, without mapToInt()
:
int pojoSum = pojoList.stream()
.reduce(0, (sum, ob) -> sum + ob.getA() + ob.getB(), Integer::sum);
For more information, see Reduction operations paragraph.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With