Почему поток с пределом бесконечен?

#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 исчерпает память.