Возьмем ArrayList
и заполните его чем-то простым:
List<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(""+i);
}
Я попытаюсь удалить один член, например, названный 5, с различными способами потока API. Для этого я определяю метод, который даст мне ConcurentModificationException
при использовании традиционной итерации с итератором.
void removeMember(String clientListener) {
list.remove(clientListener);
}
Этот код дает мне это исключение, которое я понимаю:
list.parallelStream()
.filter(string -> string.equalsIgnoreCase("5"))
.forEach(string -> removeMember(string));
Однако попытка просто stream()
, а не parallelStream()
дает исключение нулевого указателя (NPE), что для меня странно:
list.stream()
.filter(string -> string.equalsIgnoreCase("5"))
.forEach(string -> removeMember(string));
Теперь измените тип List
на LinkedList<>
. Последний код с stream()
дает мне ConcurentModificationException
, а parallelStream()
внезапно срабатывает!
Итак, вопросы.
-
Является ли внутренняя кухня
parallelStream()
(разделители и другая магия) достаточно умной, чтобы использовать удаление этого элемента дляLinkedList
? Будет ли он работать всегда? -
Почему этот NPE для
ArrayList
? Почему NPE, а неConcurentModificationException
Я имею в виду.