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.
Текст написан своими словами, примеры кода — оригинальные.