← Назад к вопросам
Как работает промежуточная операция map?
2.0 Middle🔥 81 комментариев
#Spring Framework
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Промежуточная операция map в Stream API
Операция map — одна из самых важных операций в Stream API. Она преобразует каждый элемент потока в новый элемент, создавая новый поток с преобразованными значениями.
Основной принцип
map применяет функцию преобразования к каждому элементу потока:
// Простой пример: преобразование чисел
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> doubled = numbers.stream()
.map(n -> n * 2) // Преобразование каждого элемента
.collect(Collectors.toList());
System.out.println(doubled); // [2, 4, 6, 8, 10]
Сигнатура
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
Где:
T— тип входного элементаR— тип выходного элементаFunction<T, R>— функция преобразования
Примеры использования
1. Преобразование объектов в строки
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
List<Person> people = Arrays.asList(
new Person("Alice", 25),
new Person("Bob", 30),
new Person("Charlie", 35)
);
// Получить список имён
List<String> names = people.stream()
.map(Person::getName) // Метод-ссылка
.collect(Collectors.toList());
System.out.println(names); // [Alice, Bob, Charlie]
2. Преобразование типов данных
List<String> strings = Arrays.asList("1", "2", "3", "4", "5");
List<Integer> integers = strings.stream()
.map(Integer::parseInt) // String -> Integer
.collect(Collectors.toList());
System.out.println(integers); // [1, 2, 3, 4, 5]
3. Извлечение полей из объектов
class Order {
private String id;
private double amount;
public Order(String id, double amount) {
this.id = id;
this.amount = amount;
}
public double getAmount() { return amount; }
}
List<Order> orders = Arrays.asList(
new Order("O1", 100.0),
new Order("O2", 200.0),
new Order("O3", 150.0)
);
// Получить все суммы заказов
double totalAmount = orders.stream()
.map(Order::getAmount) // Order -> Double
.mapToDouble(Double::doubleValue)
.sum();
System.out.println(totalAmount); // 450.0
Цепочки map операций
List<String> result = Arrays.asList("apple", "banana", "cherry")
.stream()
.map(String::toUpperCase) // apple -> APPLE
.map(s -> s + "!") // APPLE -> APPLE!
.map(String::length) // APPLE! -> 6
.map(String::valueOf) // 6 -> "6"
.collect(Collectors.toList());
System.out.println(result); // [6, 7, 6]
Специализированные версии map
1. mapToInt — преобразование в IntStream
List<String> numbers = Arrays.asList("1", "2", "3", "4", "5");
int sum = numbers.stream()
.mapToInt(Integer::parseInt) // Stream<String> -> IntStream
.sum();
System.out.println(sum); // 15
2. mapToLong — для больших чисел
List<Long> ids = Arrays.asList(1L, 2L, 3L, 4L, 5L);
long product = ids.stream()
.mapToLong(Long::longValue)
.reduce(1, (a, b) -> a * b);
System.out.println(product); // 120
3. mapToDouble — для дробных чисел
List<Integer> grades = Arrays.asList(80, 90, 75, 88);
double average = grades.stream()
.mapToDouble(Integer::doubleValue)
.average()
.orElse(0.0);
System.out.println(average); // 83.25
Визуализация работы map
Входящий поток: 1 2 3 4 5
| | | | |
v v v v v
Операция map(*2): 2 4 6 8 10
| | | | |
v v v v v
Исходящий поток: 2 4 6 8 10
Важное свойство: ленивость (laziness)
List<Integer> result = Arrays.asList(1, 2, 3, 4, 5)
.stream()
.map(n -> {
System.out.println("Преобразование " + n);
return n * 2;
})
.filter(n -> n > 5) // Промежуточная операция
.collect(Collectors.toList()); // Терминальная операция
// Вывод: функция map вызовется только для элементов,
// которые пройдут filter (4 -> 8, 5 -> 10)
map vs flatMap
// map — преобразование один-ко-одному
List<Integer> numbers = Arrays.asList(1, 2, 3);
List<Integer> doubled = numbers.stream()
.map(n -> n * 2)
.collect(Collectors.toList()); // [2, 4, 6]
// flatMap — преобразование один-ко-многим и выравнивание
List<List<Integer>> nestedLists = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5, 6)
);
List<Integer> flattened = nestedLists.stream()
.flatMap(List::stream) // Выравнивание списков
.map(n -> n * 2) // Преобразование
.collect(Collectors.toList()); // [2, 4, 6, 8, 10, 12]
Практический пример: обработка JSON
class User {
private String name;
private String email;
public User(String name, String email) {
this.name = name;
this.email = email;
}
public String getEmail() { return email; }
}
List<User> users = Arrays.asList(
new User("Alice", "alice@example.com"),
new User("Bob", "bob@example.com")
);
// Преобразование в строковое представление
String csvEmails = users.stream()
.map(User::getEmail)
.collect(Collectors.joining(","));
System.out.println(csvEmails); // alice@example.com,bob@example.com
Ключевые свойства map
- Промежуточная операция — не выполняется до терминальной операции
- Один-ко-одному преобразование — каждый элемент преобразуется в ровно один элемент
- Сохранение порядка — элементы остаются в том же порядке
- Ленивое вычисление — вычисляется только для нужных элементов
- Функциональная парадигма — чистые функции без побочных эффектов
map — это основной инструмент функционального программирования в Java, используется в 80% работы со Stream API.