Что такое бесконечные стримы (Stream) в Java и для чего они используются?

«Что такое бесконечные стримы (Stream) в Java и для чего они используются?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Бесконечные стримы (Infinite Streams) — это Stream, который не имеет предопределенного ограничения по количеству элементов. Он генерирует элементы "на лету" (лениво) по мере необходимости.

Для чего нужны:

  1. Работа с потенциально бесконечными последовательностями. Например, генерация случайных чисел, последовательность Фибоначчи, чтение данных из непрерывного источника (лог-файл, сетевое соединение).
  2. Ленивые вычисления. Элементы генерируются только при вызове терминальной операции (collect, limit, findFirst). Это экономит память.
  3. Создание тестовых данных или заглушек.

Способы создания:

  • Stream.generate(): Генерирует элементы с помощью поставщика (Supplier).
    // Бесконечный поток случайных чисел
    Stream<Double> randomStream = Stream.generate(Math::random);
    // Использование с ограничением
    List<Double> tenRandoms = randomStream.limit(10).toList();
  • Stream.iterate(): Создает последовательность, применяя функцию к предыдущему элементу.

    // Классический iterate (Java 8) - бесконечный
    Stream<Integer> evenNumbers = Stream.iterate(0, n -> n + 2);
    
    // Улучшенный iterate (Java 9+) с предикатом-ограничителем
    Stream<Integer> numbersUpTo100 = Stream.iterate(0, n -> n < 100, n -> n + 2);

Важно: При работе с бесконечными стримами обязательно использовать промежуточные операции-ограничители (например, limit(long n) или takeWhile(Predicate)), иначе терминальная операция будет выполняться бесконечно.