Возьмем 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Я имею в виду.