#java #java-stream
#java #java-stream
Вопрос:
Я выполнил следующий код в Eclipse:
Stream.generate(() -> "Elsa")
.filter(n -> n.length() ==4)
.sorted()
.limit(2)
.forEach(System.out::println);
Вывод:
Исключение в потоке «main» java.lang.OutOfMemoryError: пространство кучи Java
Чего я ожидал, поскольку предел равен двум:
Elsa
Elsa
Может кто-нибудь, пожалуйста, объяснить, почему это бесконечный поток?
Комментарии:
1. Вы должны взглянуть на эту часть документации. В частности
sorted
, это не ленивая операция, поэтому ей нужен весь поток.
Ответ №1:
Первое, что Stream::generate
создает бесконечный поток. Вот почему поток изначально бесконечен.
Вы ограничиваете поток двумя элементами, используя Stream::limit
, что сделало бы его конечным.
Однако проблема в том, что вы вызываете sorted()
, который пытается использовать весь поток. Вам нужно ограничить поток перед сортировкой:
Stream.generate(() -> "Elsa")
.filter(n -> n.length() == 4)
.limit(2)
.sorted()
.forEach(System.out::println);
В документации говорится, что Stream::sorted()
«это промежуточная операция с сохранением состояния». Документация Streams о промежуточной операции с сохранением состояния объясняет это очень хорошо:
Для операций с отслеживанием состояния может потребоваться обработать весь ввод до получения результата. Например, невозможно получить какие-либо результаты от сортировки потока, пока не будут просмотрены все элементы потока.
Акцент мой.
Вот оно. Также обратите внимание, что для всех потоковых операций их тип операции указан в Javadocs.
Ответ №2:
Может кто-нибудь, пожалуйста, объяснить, почему это бесконечный поток?
Потому что javadoc говорит, что это именно то, что Stream.generate()
создает:
Возвращает бесконечный последовательный неупорядоченный поток, в котором каждый элемент генерируется предоставленным поставщиком
Затем, когда вы объединяете это с sorted()
, вы говорите ему начать сортировку в бесконечной последовательности, что, очевидно, приведет к тому, что JVM исчерпает память.