Stream API з’явився в Java 8 і докорінно змінив підхід до обробки колекцій. Якщо ви досі пишете вкладені цикли для фільтрації та трансформації даних, ця стаття для вас. Розглянемо 5 практичних прикладів, які покажуть всю потужність Stream API.
1. Фільтрація та трансформація в один рядок
Завдання: Отримати список email-адрес активних користувачів, відсортованих за алфавітом.
Традиційний підхід:
List<User> users = getUserList();
List<String> activeEmails = new ArrayList<>();
for (User user : users) {
if (user.isActive()) {
activeEmails.add(user.getEmail());
}
}
Collections.sort(activeEmails);JavaЗ Stream API:
List<String> activeEmails = users.stream()
.filter(User::isActive)
.map(User::getEmail)
.sorted()
.collect(Collectors.toList());JavaКод став коротшим, читабельнішим і декларативним. Ми описуємо “що” робити, а не “як”.
2. Групування даних: створюємо Map без зусиль
Завдання: Згрупувати товари за категоріями.
Map<String, List<Product>> productsByCategory = products.stream()
.collect(Collectors.groupingBy(Product::getCategory));JavaА якщо потрібно отримати кількість товарів у кожній категорії?
Map<String, Long> countByCategory = products.stream()
.collect(Collectors.groupingBy(
Product::getCategory,
Collectors.counting()
));Java3. Пошук і перевірка: anyMatch, allMatch, noneMatch
Завдання: Перевірити, чи є серед замовлень такі, що перевищують певну суму.
boolean hasLargeOrders = orders.stream()
.anyMatch(order -> order.getTotal() > 1000);JavaПеревірити, чи всі користувачі підтвердили email:
boolean allVerified = users.stream()
.allMatch(User::isEmailVerified);JavaПереконатися, що немає заблокованих акаунтів:
boolean noBlocked = users.stream()
.noneMatch(User::isBlocked);Java4. Робота з Optional: уникаємо NullPointerException
Stream API чудово працює з Optional, роблячи код безпечнішим.
Optional<User> premiumMyUser = users.stream()
.filter(User::isPremium)
.findFirst();
// Безпечне отримання значення
String userName = premiumMyUser
.map(User::getName)
.orElse("Guest");JavaАбо виконати дію, якщо елемент знайдено:
users.stream()
.filter(u -> u.getId().equals(userId))
.findFirst()
.ifPresent(user -> sendNotification(user));Java5. Паралельна обробка: прискорюємо код
Для великих обсягів даних можна використовувати паралельні стріми.
long count = largeList.parallelStream()
.filter(item -> expensiveOperation(item))
.count();JavaУвага! Паралельні стріми не завжди швидші. Використовуйте їх для:
- Великих колекцій (тисячі елементів)
- Складних обчислень
- Коли операції незалежні одна від одної
А тепер все до купи
Реальний приклад – розрахунок середньої ціни активних товарів у певній категорії:
OptionalDouble averagePrice = products.stream()
.filter(Product::isActive)
.filter(p -> p.getCategory().equals("Electronics"))
.mapToDouble(Product::getPrice)
.average();
averagePrice.ifPresent(avg ->
System.out.println("Середня ціна: " + avg)
);JavaВисновок
Stream API робить код:
- Читабельнішим – зрозуміло з першого погляду
- Коротшим – менше boilerplate коду
- Безпечнішим – інтеграція з Optional
- Швидшим – можливість паралелізації
Почніть використовувати стріми в своїх проектах вже сьогодні, і ви побачите, як зміниться якість вашого коду!





