Что такое параллельные стримы в Java и для чего они нужны?

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

Ответ

Параллельные стримы (Parallel Streams) в Java — это механизм для автоматического распараллеливания операций над коллекциями данных, использующий ForkJoinPool. Они нужны для ускорения обработки больших объемов данных за счет использования нескольких ядер процессора.

Ключевые моменты:

  • Автоматическое распараллеливание: Достаточно вызвать .parallelStream() или .stream().parallel().
  • Использование ForkJoinPool: По умолчанию используется общий пул потоков (ForkJoinPool.commonPool()).
  • Порядок не гарантирован: Элементы обрабатываются в произвольном порядке, если не используется упорядоченная операция (например, forEachOrdered).

Пример использования:

List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Последовательная обработка
long sequentialSum = numbers.stream()
                            .mapToInt(Integer::intValue)
                            .sum();

// Параллельная обработка
long parallelSum = numbers.parallelStream()
                          .mapToInt(Integer::intValue)
                          .sum();

System.out.println("Сумма (последовательно): " + sequentialSum); // 55
System.out.println("Сумма (параллельно): " + parallelSum); // 55

Когда использовать:

  • Большие коллекции (десятки/сотни тысяч элементов).
  • «Тяжелые» операции над каждым элементом (сложные вычисления).
  • Операции не зависят от порядка (сложение, фильтрация, mapping).

Ограничения и риски:

  • Накладные расходы: Для маленьких коллекций параллельная обработка может быть медленнее из-за создания потоков.
  • Состояние: Операции должны быть stateless и non-interfering.
  • Побочные эффекты: Избегайте изменения общих переменных внутри лямбда-выражений.
  • Порядок: forEach выводит элементы в произвольном порядке.