No, there is not.
peek()
will only operate on all elements when forced to by a following operation. Can you predict what will be printed by this code?
public class Test {
private static final AtomicBoolean FLAG = new AtomicBoolean(false);
private static void setFlagIfGreaterThanZero(int val) {
if (val > 0) {
FLAG.set(true);
}
}
public static void main(String[] args) {
// Test 1
FLAG.set(false);
IntStream.range(0, 10)
.peek(Test::setFlagIfGreaterThanZero)
.findFirst();
System.out.println(FLAG.get());
// Test 2
FLAG.set(false);
IntStream.range(0, 10)
.peek(Test::setFlagIfGreaterThanZero)
.sorted()
.findFirst();
System.out.println(FLAG.get());
// Test 3
FLAG.set(false);
IntStream.range(0, 10)
.peek(Test::setFlagIfGreaterThanZero)
.filter(x -> x == 0)
.toArray();
System.out.println(FLAG.get());
// Test 4
FLAG.set(false);
IntStream.range(0, 10)
.boxed()
.peek(Test::setFlagIfGreaterThanZero)
.sorted()
.findFirst();
System.out.println(FLAG.get());
}
}
The answer is:
false
false
true
true
That output might be intuitive if you have a solid understanding of Java Streams, but hopefully it also indicates that it's a very bad idea to rely on peek()
as a mid-stream forEach()
.
map()
also suffers the same issue. As far as I'm aware, there is no Stream operation that guarantees a sort of "process every element without taking shortcuts" behavior in every case independent of the prior and following operations.
Although this can be a pain, the short-circuiting behavior of Streams is an important feature. You might find this excellent answer to another question on this topic to be useful.