Ответ 1
Ваш код не рекурсивно зацикливается. Вы можете протестировать с меньшими номерами для диапазона IntStream (то есть 1 или 100). В вашем случае это фактическое ограничение размера стека, которое вызывает проблему. Как отмечалось в некоторых комментариях, это то, как потоки являются процессами.
Каждый вызов в потоке создает новый поток обертки вокруг исходного. Метод findFirst() запрашивает предыдущий поток для элементов, который, в свою очередь, запрашивает предыдущий поток для элементов. Поскольку потоки не являются реальными контейнерами, а только указатели на элементы результата.
Взрыв оболочки происходит в накопителе методов уменьшения (str, abc) → abc.process(str). Реализация метода создает новую обертку потока на результат (str) предыдущей операции, подавая на следующую итерацию, создавая новую оболочку результата (результат (str))). Таким образом, механизм накопления является одной из обертки (рекурсии), а не приложения (итерации). Поэтому создание нового потока фактического (сплющенного) результата, а не ссылки на потенциальный результат, остановит взрыв, т.е.
public Stream<String> process(Stream<String> batch) {
return Stream.of(batch.map(this::doNothing).collect(Collectors.joining()));
}
Этот метод является всего лишь примером, поскольку ваш оригинальный пример не имеет никакого смысла, потому что он ничего не делает, и этот пример тоже. Это просто иллюстрация. Он в основном выравнивает элементы потока, возвращаемого методом карты, в одну строку и создает новый поток на этой конкретной строке, а не на самом потоке, это разница с исходным кодом.
Вы можете настроить stacksize с помощью параметра -Xss, который определяет размер стека для потока. Значение по умолчанию зависит от платформы, см. Также этот вопрос "Какова максимальная глубина стека вызовов java?" Но будьте осторожны при увеличении, этот параметр применяется ко всем потоки.