How can a sum be calculated using the Stream API with nested foreach loops where each has a filter condition?
//java7
Double sum = null;
for (FirstNode first : response.getFirstNodes()) {
if (first.isValid()) {
for (SndNnode snd : first.getSndNodes()) {
if (snd.getType() == NodeType.AMOUNT) {
sum += snd.getAmount();
break;
}
}
}
}
//java8
response.getFirstNodes().stream().filter(first -> first.isValid()).mapToDouble(???).sum();
My snd
foreach loop would be:
first.getSndNodes().stream().filter(snd -> snd.getType() == NodeType.AMOUNT).mapToDouble(snd -> snd.getAmount()).findFirst().sum();
How could I now integrate the snd foreach loop into the first, to get a global sum of the nested lists?
You could use flatMap
:
response.getFirstNodes()
.stream()
.filter(first -> first.isValid())
.flatMap(first -> first.getSndNodes().stream())
.filter(snd -> snd.getType() == NodeType.AMOUNT)
.mapToDouble(snd -> snd.getAmount())
.sum();
I'm not sure whether that break;
is intentional in your original code.
With the break;
statement, it should looks like this:
response.getFirstNodes()
.stream()
.filter(first -> first.isValid())
.map(first -> first.getSndNodes().stream().filter(snd -> snd.getType() == NodeType.AMOUNT).findFirst())
.filter(Optional::isPresent)
.mapToDouble(opt -> opt.get().getAmount())
.sum();
Basically, for each FirstNode
you test whether it's valid, then you map each FirstNode
to a stream of its SndNode
s for which you find the first that has the type NodeType.AMOUNT
. You need then to filter to get only Optionals that are not empty and for them you get the SndNode
they contains for which you get the corresponding amount.