Сколько раз вызовется операция peek в Java Stream с фильтром и findFirst
Что проверяют
Понимаете ли вы, что стрим это конвейер, а не коллекция: элементы идут по цепочке по одному, а не проходят её целиком на каждом шаге. Вопрос про число вызовов peek проверяет ровно это плюс знание короткого замыкания у терминальных операций.
Как отвечать
Первым делом скажите, что ответ зависит от порядка операций, и разберите оба варианта.
Stream.of(1, 2, 3, 4, 5)
.peek(n -> System.out.println("peek " + n))
.filter(n -> n > 3)
.findFirst();Здесь элементы тянутся по одному: единица проходит peek, не проходит фильтр, берётся двойка и так далее. peek вызовется четыре раза, до первого подходящего элемента включительно. Если поставить peek после filter, он вызовется один раз: до него доедет только четвёрка.
Дальше объясните механику. filter и peek промежуточные и ленивые, они ничего не считают до терминальной операции. findFirst терминальная и с коротким замыканием, она обрывает конвейер на первом результате. Если подходящих элементов нет, peek отработает на всех и вернётся пустой Optional.
Отдельный балл за оговорку: sorted или distinct в цепочке требуют увидеть весь поток, и экономии от короткого замыкания уже не будет.
Где спотыкаются
Считают, что сначала весь поток проходит через peek, потом весь через filter. Это модель коллекций, при ней ответ получается равным длине источника, и ошибка сразу видна интервьюеру.
Второе: используют peek для побочных эффектов в рабочем коде. Документация описывает его как средство отладки, а движок вправе вообще его не вызвать, если результат не нужен: count() на потоке с известным размером может пропустить конвейер целиком, и логика внутри peek молча перестанет выполняться.
Третье: переносят подсчёт на параллельный стрим. Порядок обхода там не слева направо, findFirst вернёт тот же элемент, но отработать peek успеет на большем числе элементов, и предсказуемого числа вызовов уже нет.