Antaaaa
Antaaaa

Reputation: 233

Java: Why ConcurrentModificationException doesnt occur while using Stream+Iterator?

I was reading some info about iterators, enumeration, etc. So I tested some code to check everything out.

First one example:

List<String> list = new ArrayList<>();
list.add("5");
list.add("1");
list.add("2");
list.add("3");
Iterator<String> iterator = list.iterator();
list.remove("1");
iterator.forEachRemaining(System.out::println);

This code makes the correct and expected output:

Exception in thread "main" java.util.ConcurrentModificationException

But when I tested the same code with only 1 change list.iterator() -> list.stream().iterator()

List<String> list = new ArrayList<>();
list.add("5");
list.add("1");
list.add("2");
list.add("3");
Iterator<String> iterator = list.stream().iterator();
list.remove("1");
iterator.forEachRemaining(System.out::println);

The result was:

5
2
3

My main aim is to understand:

  1. Why is this happens?
  2. What magic makes only one stream() method?
  3. What are the advantages and disadvantages of using stream().iterator?

Upvotes: 4

Views: 155

Answers (1)

Andreas
Andreas

Reputation: 159086

When you call stream(), the API internally calls spliterator(), which it similar to iterator().

For ArrayList, the returned Spliterator / Iterator uses an expectedModCount field to compare to the modCount field of the list, to check if the list has been modified.

The implementation of Iterator initializes the expectedModCount field when the iterator is created.

The implementation of Spliterator defers that initialization until the first element is taken from the Spliterator.

Which means that it allows modification of the list between the call to stream() and the call to the terminal operation that actually starts pulling data from the stream.

Upvotes: 5

Related Questions