Stream filter и map

filter и map — две самые частые промежуточные операции Stream API. filter пропускает дальше только те элементы, которые удовлетворяют условию (Predicate). map преобразует каждый элемент в новый (Function). Вместе они покрывают, наверное, 80% задач по обработке коллекций.

Дополнительно есть mapToInt / mapToLong / mapToDouble — переводят поток объектов в специализированный примитивный поток (без боксинга), и flatMap — «разворачивает» поток потоков в один общий поток.

Сигнатуры

Stream<T> filter(Predicate<? super T> predicate)
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
IntStream     mapToInt(ToIntFunction<? super T> mapper)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)

Примеры

Пример 1. filter

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FilterDemo {
    public static void main(String[] args) {
        List<Integer> distances = Arrays.asList(2, 15, 8, 30, 50, 5);
        List<Integer> safe = distances.stream()
                                      .filter(d -> d >= 10 && d <= 40)
                                      .collect(Collectors.toList());
        System.out.println(safe);
    }
}

Output:

[15, 30]

Пример 2. map

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class MapDemo {
    public static void main(String[] args) {
        List<Integer> cm = Arrays.asList(10, 25, 100);
        List<Double> meters = cm.stream()
                                .map(v -> v / 100.0)
                                .collect(Collectors.toList());
        System.out.println(meters);
    }
}

Output:

[0.1, 0.25, 1.0]

Пример 3. filter + map в цепочке

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FilterMapChain {
    public static void main(String[] args) {
        List<String> sensors = Arrays.asList("ик", "уз", "линия", "сервопривод");
        List<String> result = sensors.stream()
                                     .filter(s -> s.length() > 3)
                                     .map(String::toUpperCase)
                                     .collect(Collectors.toList());
        System.out.println(result);
    }
}

Output:

[ЛИНИЯ, СЕРВОПРИВОД]

Пример 4. mapToInt и сумма

import java.util.Arrays;
import java.util.List;

public class MapToIntDemo {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("робот", "ИК", "ультразвук");
        int totalChars = words.stream()
                              .mapToInt(String::length)
                              .sum();
        double avg = words.stream()
                          .mapToInt(String::length)
                          .average()
                          .orElse(0);
        System.out.println("Всего символов: " + totalChars);
        System.out.println("Средняя длина: " + avg);
    }
}

Output:

Всего символов: 17
Средняя длина: 5.666666666666667

Пример 5. flatMap

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FlatMapDemo {
    public static void main(String[] args) {
        List<List<Integer>> nested = Arrays.asList(
            Arrays.asList(1, 2, 3),
            Arrays.asList(4, 5),
            Arrays.asList(6)
        );
        List<Integer> flat = nested.stream()
                                   .flatMap(List::stream)
                                   .collect(Collectors.toList());
        System.out.println(flat);
    }
}

Output:

[1, 2, 3, 4, 5, 6]

Пример 6. Разбиение строк через flatMap

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FlatMapSplit {
    public static void main(String[] args) {
        List<String> lines = Arrays.asList("ИК УЗ", "Линия", "Серво Bluetooth");
        List<String> words = lines.stream()
                                  .flatMap(s -> Arrays.stream(s.split(" ")))
                                  .collect(Collectors.toList());
        System.out.println(words);
    }
}

Output:

[ИК, УЗ, Линия, Серво, Bluetooth]

Подводные камни

Предупреждение

  • map не меняет количество элементов, filter не меняет их тип. Если перепутали — компилятор подскажет, но логика может «потеряться».

  • Для примитивов используйте mapToInt / mapToDouble — это быстрее и даёт удобные методы sum, average, min, max.

  • flatMap ждёт функцию, возвращающую Stream. Если вы вернёте сам список — это будет map, а не flatMap.

  • Внутри map / filter не должно быть побочных эффектов: операция должна быть «чистой», иначе параллельные потоки сломаются.

См. также

Примечание

Материал подготовлен по мотивам документации пакета java.util.stream и распространяется в рамках Oracle Free Documentation License. Текст написан своими словами, примеры кода — оригинальные.