Reputation: 1295
I have the following structure:
class Object1 {
String id;
Integer total;
}
class Object2 {
String id;
List<Object3> list;
}
class Object3 {
Integer total;
}
When Object1
and Object2
have the same id
I need to update the total
from Object1 by summing up the total
from all the Object3
within the list
inside Object2
and subtracting from Object1
total
.
It works like this without Java 8:
for (Object1 object1 : list1) {
for (Object2 object2 : list2) {
if (object1.getId().equals(object2.getId())) {
int total = 0;
for (Object3 object3 : object2.getlist3()) {
total += object3.getTotal();
}
object1.setTotal(object1.getTotal() - total);
}
}
}
This is what I have so far using Java 8:
list1.forEach(object1 -> list2.stream()
.filter(object2 ->object2.getId().equals(object1.getId()))
But I don't know how to proceed with the logic because I am not very familiar with Java 8.
Upvotes: 1
Views: 110
Reputation: 44150
Try this. Explanations are inline as comments
list1.forEach(object1 ->
object1.setTotal(
object1.getTotal() - list2.stream()
.filter(object2 -> object1.getId().equals(object2.getId()))
.flatMap(object2 -> object2.getList3().stream()) // Stream<Object2> to Stream<Object3>
.mapToInt(Object3::getTotal) // get each total
.sum() // sum them
)
);
It is worth noting that you are calling object1.setTotal
multiple times if more than one ID matches, effectively overriding the previous result. You may say that this is fine, and that the lists are populated in a such a way that there will only be one matching ID. In which case, you should add a break
statement after object1.setTotal
. This will avoid iterating over the remaining elements in list2
unnecessarily. A similar performance enhancement in a stream would require a significant change to the above example.
Upvotes: 3