Что выведется в консоль при использовании Stream с map и anyMatch с предикатом, который всегда возвращает true, и почему
Что проверяют
Понимаете ли вы, что стрим ленив, а терминальная операция бывает короткозамкнутой. Правильный ответ здесь не слово true, а объяснение, сколько раз выполнится функция внутри map.
Как отвечать
Напечатается true. Интереснее другое: map отработает ровно один раз, а не для всех элементов.
boolean result = Stream.of(1, 2, 3)
.map(n -> { System.out.println("map " + n); return n * 2; })
.anyMatch(n -> true);
// в консоли: map 1
System.out.println(result); // trueПромежуточные операции не делают ничего, пока не вызвана терминальная. Когда вызвана, элементы идут по конвейеру по одному: первый проходит через map, попадает в предикат, тот возвращает true, и anyMatch немедленно прекращает обход. Остальные элементы источника даже не читаются.
Стоит добавить про пустой источник: anyMatch на пустом стриме вернёт false при любом предикате, а allMatch и noneMatch вернут true, потому что проверять нечего. И что в параллельном стриме число вызовов map заранее не определено.
Где спотыкаются
Описывают работу так, будто map строит новую коллекцию, а anyMatch идёт уже по ней. Это модель цикла за циклом, а у стрима один проход, где каждый элемент протягивается через всю цепочку.
Кладут в map побочный эффект: запись в базу, отправку письма, добавление в список. С короткозамкнутой терминальной операцией эффект случится для части элементов, а без терминальной операции не случится вовсе. Функция в map обязана быть чистой, для побочных действий есть forEach.
Путают, что вернут allMatch и anyMatch на пустом источнике, и пробуют переиспользовать стрим. Повторный вызов терминальной операции на том же стриме даёт IllegalStateException, источник нужно открывать заново.