How can a sum be calcaulated using 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.
Your attempt is close to the right solution
response.getFirstNodes().stream()
.filter(FirstNode::isValid)
.mapToDouble(first ->
first.getSndNodes().stream()
.filter(snd -> snd.getType() == NodeType.AMOUNT)
.mapToDouble(snd -> snd.getAmount())
.findAny().orElse(0))
.sum();
If you are sure that there is at most one match in the inner stream, you can use findAny
as there is no requirement on the ordering then. I used the simplest solution for dealing with the possible absence of a match by replacing it with 0
which is transparent to the sum
and saves us from additional filtering.
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