Reputation: 150
I have a list of integers and I need to find the sum of its items. If the list contains any null
items, the result should be null
. My current implementation:
intList.stream().anyMatch(Objects::isNull) ? null : intList.stream().mapToInt(Integer::intValue).sum();
Can this be done with a single continuous stream? Is there an operation that terminates the stream if an item meets a condition?
Upvotes: 3
Views: 1336
Reputation: 3400
As for your question "Is there an operation that terminates the stream if an item meets a condition?", Java 9 introduces Stream::takeWhile
which does this.
However, using this for your use case would result in a sum of everything before the null (not what you are expecting of actually returning a null). For your case, and being limited to the JDK, using the answer proposed by M A is the best (though it does not stop when it reaches a null).
The actual best way would be if there is a takeWhileInclusive
combined with the reduce operation. Unfortunately, takeWhileInclusive
does not exist in the JDK. However, Tagir Valeev, who is a committer in the JDK, has written a stream extension library (StreamEx) which has StreamEx::takeWhileInclusive
. It might be useful.
The following example, using that library, would step out with a null if null is encountered, or with the sum if it is not:
StreamEx.of(intList).takeWhileInclusive(Objects::nonNull)
.reduce(0, (a, b) -> a == null || b == null ? null : a + b);
Upvotes: 3
Reputation: 40047
Streams are not always the right solution. And even when they are they may not be as efficient as a simple loop solution. In your case, I would do the following:
public static Integer sum(List<Integer> vals) {
int sum = 0;
for (Integer v : vals) {
if (v == null) {
return null;
}
sum += v;
}
return sum;
}
This both sums the elements or short circuits and returns a null.
Upvotes: 1
Reputation: 16498
May be using reduce like:
List<Integer> intList = Arrays.asList(1,2,3,null,4);
Integer sum = intList.stream().reduce(0, (a, b) -> a == null || b == null ? null: a + b);
System.out.println(sum);
Upvotes: 2
Reputation: 72884
You can control how the sum reduction occurs:
Integer sum = intList.stream().reduce(0, (i1, i2) -> {
if(i1 == null) return null;
if(i2 == null) return null;
return i1 + i2;
});
Upvotes: 2