Что такое Streams
Java Streams API (появился в Java 8) — это инструмент для функциональной обработки коллекций. Стримы позволяют обрабатывать данные декларативно, без изменения исходной коллекции.
▸Ключевые особенности
Создание стримов
1// Из коллекции2List<String> names = List.of("Alice", "Bob", "Charlie");3Stream<String> stream = names.stream();45// Из массива6int[] numbers = {1, 2, 3, 4, 5};7IntStream arrayStream = Arrays.stream(numbers);89// Из значений10Stream<String> valueStream = Stream.of("a", "b", "c");1112// Генерация13Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);14Stream<Double> randomStream = Stream.generate(Math::random);
Промежуточные операции
▸map
1List<String> names = List.of("alice", "bob", "charlie");23List<String> upperNames = names.stream()4 .map(String::toUpperCase)5 .collect(Collectors.toList());6// [ALICE, BOB, CHARLIE]
▸filter
1List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8);23List<Integer> evenNumbers = numbers.stream()4 .filter(n -> n % 2 == 0)5 .collect(Collectors.toList());6// [2, 4, 6, 8]
▸flatMap
1List<List<Integer>> lists = List.of(2 List.of(1, 2, 3),3 List.of(4, 5, 6),4 List.of(7, 8, 9)5);67List<Integer> flat = lists.stream()8 .flatMap(Collection::stream)9 .collect(Collectors.toList());10// [1, 2, 3, 4, 5, 6, 7, 8, 9]
▸sorted
1List<String> sorted = names.stream()2 .sorted()3 .collect(Collectors.toList());45// С пользовательским компаратором6List<User> sortedByAge = users.stream()7 .sorted(Comparator.comparing(User::getAge))8 .collect(Collectors.toList());
▸distinct
1List<Integer> unique = List.of(1, 2, 2, 3, 3, 3).stream()2 .distinct()3 .collect(Collectors.toList());4// [1, 2, 3]
▸peek (для отладки)
1List<String> result = names.stream()2 .filter(name -> name.length() > 3)3 .peek(name -> System.out.println("After filter: " + name))4 .map(String::toUpperCase)5 .peek(name -> System.out.println("After map: " + name))6 .collect(Collectors.toList());
Терминальные операции
▸collect
1// В список2List<String> list = stream.collect(Collectors.toList());34// В Set5Set<String> set = stream.collect(Collectors.toSet());67// В Map8Map<String, Integer> map = stream.collect(9 Collectors.toMap(User::getName, User::getAge));1011// Группировка12Map<String, List<User>> byDepartment = users.stream()13 .collect(Collectors.groupingBy(User::getDepartment));1415// Разделение16Map<Boolean, List<User>> partitioned = users.stream()17 .collect(Collectors.partitioningBy(User::isActive));
▸reduce
1// Сумма чисел2int sum = numbers.stream()3 .reduce(0, Integer::sum);45// Конкатенация строк6String result = words.stream()7 .reduce("", (a, b) -> a.isEmpty() ? b : a + ", " + b);89// Максимальный элемент10Optional<Integer> max = numbers.stream()11 .reduce(Integer::max);
▸forEach
1names.stream()2 .filter(name -> name.length() > 3)3 .forEach(System.out::println);
▸min/max/count
1Optional<Integer> min = numbers.stream().min(Integer::compareTo);2Optional<Integer> max = numbers.stream().max(Integer::compareTo);3long count = numbers.stream().filter(n -> n > 5).count();
▸anyMatch/allMatch/noneMatch
1boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0);2boolean allPositive = numbers.stream().allMatch(n -> n > 0);3boolean noneNegative = numbers.stream().noneMatch(n -> n < 0);
▸findFirst/findAny
1Optional<String> first = names.stream()2 .filter(name -> name.startsWith("A"))3 .findFirst();45Optional<String> any = names.parallelStream()6 .filter(name -> name.length() > 5)7 .findAny();
Параллельные стримы
1// Последовательный2long sequential = numbers.stream()3 .filter(n -> n > 5)4 .count();56// Параллельный7long parallel = numbers.parallelStream()8 .filter(n -> n > 5)9 .count();
▸Когда использовать параллельные стримы
Практические примеры
▸Трансформация данных
1List<String> emails = users.stream()2 .filter(User::isActive)3 .map(User::getEmail)4 .filter(email -> email.endsWith("@company.com"))5 .sorted()6 .distinct()7 .collect(Collectors.toList());
▸Группировка и агрегация
1Map<String, Double> avgSalaryByDept = employees.stream()2 .collect(Collectors.groupingBy(3 Employee::getDepartment,4 Collectors.averagingDouble(Employee::getSalary)5 ));
▸Поиск и сортировка
1Optional<Product> mostExpensive = products.stream()2 .filter(p -> p.getCategory().equals("electronics"))3 .max(Comparator.comparing(Product::getPrice));
Заключение
Java Streams — мощный инструмент для функционального программирования. На собеседовании обязательно спросят про разницу между промежуточными и терминальными операциями, lazy evaluation, parallel streams и типичные паттерны использования. Практикуйтесь с реальными задачами трансформации данных.