← Назад к вопросам

С каким функциональным интерфейсом взаимодействует map

1.6 Junior🔥 291 комментариев
#Коллекции

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Функциональный интерфейс для метода map

Метод map() в Stream API взаимодействует с функциональным интерфейсом Function<T, R>, который определён в пакете java.util.function.

Определение Function

@FunctionalInterface
public interface Function<T, R> {
    // Основной метод
    R apply(T t);
    
    // Дополнительные методы (default)
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        return (V v) -> apply(before.apply(v));
    }
    
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        return (T t) -> after.apply(apply(t));
    }
    
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

T - тип входных данных (input type) R - тип результата (return type)

Использование map с Function

Stream<String> stream = Stream.of("apple", "banana", "cherry");

// map принимает Function<String, Integer>
Stream<Integer> lengths = stream.map(str -> str.length());
lengths.forEach(System.out::println);
// Вывод: 5 6 6

Примеры различных трансформаций

List<String> fruits = Arrays.asList("apple", "banana", "cherry");

// 1. Преобразование String в Integer
List<Integer> lengths = fruits.stream()
    .map(fruit -> fruit.length())  // Function<String, Integer>
    .collect(Collectors.toList());
// Результат: [5, 6, 6]

// 2. Преобразование Integer в String
List<Integer> numbers = Arrays.asList(1, 2, 3);
List<String> stringNumbers = numbers.stream()
    .map(num -> String.valueOf(num))  // Function<Integer, String>
    .collect(Collectors.toList());
// Результат: ["1", "2", "3"]

// 3. Преобразование объекта в его свойство
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", 30),
    new Person("Bob", 25),
    new Person("Charlie", 35)
);

List<String> names = people.stream()
    .map(Person::getName)  // Function<Person, String>
    .collect(Collectors.toList());
// Результат: ["Alice", "Bob", "Charlie"]

Различные способы использования Function

1. Лямбда выражение

Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> doubled = numbers.map(n -> n * 2);
// Результат: 2, 4, 6, 8, 10

2. Method Reference

List<String> words = Arrays.asList("hello", "world");
List<String> upper = words.stream()
    .map(String::toUpperCase)  // Function<String, String>
    .collect(Collectors.toList());
// Результат: ["HELLO", "WORLD"]

3. Анонимный класс

Stream<Integer> numbers = Stream.of(1, 2, 3);
Stream<Integer> squared = numbers.map(new Function<Integer, Integer>() {
    @Override
    public Integer apply(Integer n) {
        return n * n;
    }
});

4. Ссылка на конструктор

List<String> names = Arrays.asList("Alice", "Bob");
List<Integer> ages = Arrays.asList(30, 25);

Stream<Person> people = Stream.of(
    new Person("Alice", 30),
    new Person("Bob", 25)
);

List<String> personNames = people.stream()
    .map(Person::getName)  // Function<Person, String>
    .collect(Collectors.toList());

Сравнение map с другими методами Stream

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// map - преобразует тип (Function<T, R>)
List<Integer> doubled = numbers.stream()
    .map(n -> n * 2)  // Function<Integer, Integer>
    .collect(Collectors.toList());
// Результат: [2, 4, 6, 8, 10]

// filter - оставляет элементы (Predicate<T>)
List<Integer> evens = numbers.stream()
    .filter(n -> n % 2 == 0)  // Predicate<Integer>
    .collect(Collectors.toList());
// Результат: [2, 4]

// forEach - выполняет действие (Consumer<T>)
numbers.stream()
    .forEach(n -> System.out.println(n));  // Consumer<Integer>

// reduce - комбинирует элементы (BinaryOperator<T>)
int sum = numbers.stream()
    .reduce(0, (a, b) -> a + b);  // BinaryOperator<Integer>
// Результат: 15

Цепочка map операций

List<String> words = Arrays.asList("hello", "world", "java");

List<Integer> result = words.stream()
    .map(String::toUpperCase)      // Function<String, String>
    .map(String::length)           // Function<String, Integer>
    .map(len -> len * 2)           // Function<Integer, Integer>
    .collect(Collectors.toList());
// Результат: [10, 10, 8]

flatMap - специальный вариант

// map для вложенных структур
List<List<Integer>> lists = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4),
    Arrays.asList(5, 6)
);

// map преобразует List<Integer> -> Stream<Integer>
// но остаёт Stream<Stream<Integer>>
Stream<Stream<Integer>> streamOfStreams = lists.stream()
    .map(List::stream);  // Function<List<Integer>, Stream<Integer>>

// flatMap - развёртывает (распрямляет) результат
List<Integer> flat = lists.stream()
    .flatMap(List::stream)  // Function<List<Integer>, Stream<Integer>>
    .collect(Collectors.toList());
// Результат: [1, 2, 3, 4, 5, 6]

Практический пример: обработка JSON

class User {
    private String name;
    private String email;
    
    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }
    
    public String getName() { return name; }
    public String getEmail() { return email; }
}

List<User> users = Arrays.asList(
    new User("Alice", "alice@example.com"),
    new User("Bob", "bob@example.com")
);

// Преобразование User в JSON-подобную строку
List<String> json = users.stream()
    .map(user -> "{\"name\":\"" + user.getName() + 
                 "\",\"email\":\"" + user.getEmail() + "\"}")
    .collect(Collectors.toList());
// Результат: [{"name":"Alice","email":"alice@example.com"}, ...]

Другие функциональные интерфейсы для Stream

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// map -> Function<T, R>
numbers.stream().map(n -> n * 2);

// filter -> Predicate<T>
numbers.stream().filter(n -> n > 2);

// forEach -> Consumer<T>
numbers.stream().forEach(System.out::println);

// reduce -> BinaryOperator<T> (функция от двух T к T)
int sum = numbers.stream().reduce(0, (a, b) -> a + b);

// sorted -> Comparator<T>
numbers.stream().sorted((a, b) -> b - a);

// collect -> Collector<T, A, R>
numbers.stream().collect(Collectors.toList());

Вывод

map() использует Function<T, R>, где:

  • T - исходный тип элементов потока
  • R - тип результата после трансформации

Это позволяет преобразовывать элементы потока в элементы нового потока с другим типом данных. Function - это один из основных функциональных интерфейсов в Java, предоставляющий простой способ определить трансформацию данных.