When I run the following code
List<Integer> list = IntStream.range(0,10).boxed().collect(Collectors.toList());
list.stream().forEach(i -> {
System.out.println("i:" +i);
if (i==5) {
System.out.println("..adding 22");
list.add(22);
}
});
I get the following output:
i:0
i:1
i:2
i:3
i:4
i:5
..adding 22
i:6
i:7
i:8
i:9
Exception in thread "main" java.util.ConcurrentModificationException
Why is the code progressing beyond index 5? I would not have expected the following lines in the output:
i:6
i:7
i:8
i:9
I am missing something here, regarding the behaviour perhaps of forEach. The documentation does state "The behavior of this operation is explicitly nondeterministic." and goes on to talk about parallel streams. I would expect parallel streams to execute forEach in any order whatsoever, but surely serial streams execute the Consumer fed to forEach serially? And if so, why is Java allowing the code to progress beyond the exception generated at index 5? There's one thread here, correct?
Thank you in advance.
Edit: Thank you for answers so far. To be absolutely clear my point is that if I do this:
for(int i: list){
System.out.println("i:" +i);
if(i==5) {
System.out.println("..adding 22");
list.add(22);
}
}
I get this:
i:0
i:1
i:2
i:3
i:4
i:5
..adding 22
Exception in thread "main" java.util.ConcurrentModificationException
but I do not get that in a forEach. So it seems a serial stream forEach is NOT analagous to an iterator, either a hand cranked (Iterator iter = list.iterator...) or an enhanced for loop iterator. This was unexpected to me. But it seems from answers given that this is for "performance reasons". But still it's...unexpected. Just for kicks I tried it with a list of 1m elements:
List<Integer> list = IntStream.range(0,1000000).boxed().collect(Collectors.toList());
list.stream().forEach(
i -> {
if(i%250000==0)
System.out.println("i:" +i);
if(i>999997)
System.out.println("i:" +i);
if(i==5) {
System.out.println("..adding 22");
list.add(22);
}}
);
And I got the (now expected) following output:
i:0
..adding 22
i:250000
i:500000
i:750000
i:999998
i:999999
Exception in thread "main" java.util.ConcurrentModificationException
So as been said, the check it seems is done at the end.