Stream API и параллельные потоки в Java (4/10)

⚠️ В этом посте я не учу Stream API — я показываю, как Java может обрабатывать большие наборы данных параллельно и просто. Для запуска используйте JDK 17+ и любую IDE.

Мы уже научились запускать потоки, синхронизировать их и писать асинхронный код. Теперь давай посмотрим, как Java умеет ускорять обработку данных буквально одной строкой — без ручного управления потоками.

Иногда не нужно создавать Thread — просто добавь .parallel()

☕ Пример: считаем кофе по регионам

Допустим, у нас есть список заказов из разных регионов. Мы хотим посчитать, сколько кофе сварили в каждом регионе.

import java.util.; import java.util.stream.;

public class CoffeeStats { public static void main(String[] args) { List orders = Arrays.asList( "Asia", "Europe", "Europe", "Asia", "America", "Asia", "Europe", "America", "Europe", "Asia" );

Map stats = orders .parallelStream() // магия начинается здесь .collect(Collectors.groupingBy(region -> region, Collectors.counting()));

stats.forEach((region, count) -> System.out.println("🌍 " + region + ": " + count + " чашек кофе")); } }

⚡ Что делает .parallelStream()?

  1. Делит список на подзадачи. 2( Обрабатывает их в нескольких потоках.
  2. Собирает результат автоматически.

То есть Java сама решает, как распределить нагрузку по ядрам процессора. Ты просто пишешь декларативно - “что” нужно сделать, а не “как”.

Сравнение: stream vs parallelStream

orders.stream().forEach(System.out::println); // последовательно orders.parallelStream().forEach(System.out::println); // параллельно

Второй вариант выведет строки в разном порядке — потому что потоки работают независимо. Если порядок важен — используй .forEachOrdered().

🧩 Когда параллельные потоки — благо, а когда нет

✅ Отлично подходят, если:

  1. Много независимых элементов для обработки.
  2. CPU имеет несколько ядер.
  3. Задачи CPU-bound (тяжёлые вычисления).

❌ Лучше не использовать, если: 4) Мало данных (накладные расходы будут больше). 5) Есть взаимодействие с внешними ресурсами (файлы, БД, сеть). 6) Порядок важен и нельзя его нарушать.

🔍 Продвинутый пример. Можно комбинировать фильтрацию, маппинг и группировку — всё параллельно:

Map hotRegions = orders .parallelStream() .filter(region -> !region.equals("America")) .collect(Collectors.groupingBy(r -> r, Collectors.counting()));

System.out.println("🔥 Активные регионы: " + hotRegions);

🧭 Итоги

  1. .parallelStream() — быстрый способ параллелить задачи без лишнего кода.
  2. Работает “из коробки” - Java сама решает, сколько потоков нужно.
  3. Помогает эффективно использовать многоядерные процессоры.
  4. Параллельность - не всегда панацея, думай о балансе.

Как и в жизни: иногда стоит делать всё сразу, а иногда - просто по порядку и с умом. Главное - знать, когда включать наш так называемый “параллельный режим”.