Что такое stateful и stateless операции в Java Stream API
Что проверяют
Понимаете ли вы, что часть операций вынуждена накапливать данные, и знаете ли, чем это оборачивается для порядка и параллелизма.
Как отвечать
Без состояния (stateless): обработка элемента не зависит от других. filter, map, flatMap, peek. Такие операции проходят элементы по одному и хорошо параллелятся.
С состоянием (stateful): результат зависит от других элементов, поэтому операции нужно видеть больше одного за раз. sorted, distinct, limit, skip.
Практические следствия:
sortedиdistinctтребуют полного прохода и буферизации перед тем, как выдать первый элемент. На бесконечном стримеsortedне завершится никогда;- порядок операций меняет стоимость:
sorted().limit(10)сортирует всё,limit(10).sorted()только десять. Смысл при этом разный, и подменять одно другим нельзя; - в параллельном стриме операции с состоянием стоят дороже:
distinctиsortedтребуют синхронизации и объединения промежуточных результатов, аlimitна упорядоченном стриме заставляет соблюдать порядок и почти лишает выигрыша.
Отдельно стоит сказать про короткое замыкание: limit, findFirst, anyMatch могут завершить конвейер, не обработав все элементы. Именно поэтому ленивость важна: без неё findFirst на миллионе элементов стоил бы как полный проход.
Где спотыкаются
Ставят sorted перед filter и сортируют лишнее.
Применяют sorted к бесконечному стриму.
Ждут ускорения от parallelStream там, где вся цепочка состоит из операций с состоянием.
Пишут distinct для объектов без корректных equals и hashCode и не понимают, почему дубли остались.