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

Что такое Function?

2.0 Middle🔥 181 комментариев
#Основы Java

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

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

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

# Что такое Function

Function — это функциональный интерфейс в Java (java.util.function.Function<T, R>), который представляет функцию, принимающую один аргумент типа T и возвращающую результат типа R.

Базовое определение

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t); // Основной метод
}

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

1. Простое преобразование

// Function для преобразования строки в длину
Function<String, Integer> stringLength = s -> s.length();
int length = stringLength.apply("Hello"); // 5

// Function для преобразования числа в квадрат
Function<Integer, Integer> square = x -> x * x;
int result = square.apply(5); // 25

2. Отображение в Stream

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// map использует Function для преобразования каждого элемента
List<Integer> lengths = names.stream()
    .map(String::length) // Function: String -> Integer
    .collect(Collectors.toList()); // [5, 3, 7]

// Полностью эквивалентно
Function<String, Integer> lengthFunc = String::length;
List<Integer> lengths2 = names.stream()
    .map(lengthFunc)
    .collect(Collectors.toList());

3. Преобразование объектов

public class Person {
    private String name;
    private int age;
    
    // Конструкторы и геттеры
}

// Function для преобразования Person в String (имя)
Function<Person, String> getName = person -> person.getName();
// ИЛИ
Function<Person, String> getName2 = Person::getName;

List<Person> people = Arrays.asList(
    new Person("Alice", 25),
    new Person("Bob", 30)
);

List<String> names = people.stream()
    .map(getName) // Преобразуем каждого Person в его имя
    .collect(Collectors.toList()); // ["Alice", "Bob"]

Композиция Function

andThen() — цепочка операций

Function<Integer, Integer> addOne = x -> x + 1;
Function<Integer, Integer> multiplyByTwo = x -> x * 2;

// Сначала добавляем 1, потом умножаем на 2
Function<Integer, Integer> composed = addOne.andThen(multiplyByTwo);

int result = composed.apply(5); // (5 + 1) * 2 = 12

compose() — реверсный порядок

// Сначала умножаем на 2, потом добавляем 1
Function<Integer, Integer> composed2 = addOne.compose(multiplyByTwo);

int result2 = composed2.apply(5); // (5 * 2) + 1 = 11

Цепочка преобразований

Function<String, String> toUpperCase = String::toUpperCase;
Function<String, Integer> getLength = String::length;
Function<Integer, String> toString = Object::toString;

// Цепочка: "hello" -> "HELLO" -> 5 -> "5"
Function<String, String> pipeline = toUpperCase
    .andThen(getLength)
    .andThen(toString);

String result = pipeline.apply("hello"); // "5"

Встроенные и производные Function интерфейсы

BiFunction — две входные переменные

BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
int sum = add.apply(5, 3); // 8

// Используется в Map.compute()
Map<String, Integer> map = new HashMap<>();
map.put("count", 5);
map.compute("count", (k, v) -> v + 1); // 6

UnaryOperator — тот же тип входа и выхода

// UnaryOperator<T> = Function<T, T>
UnaryOperator<Integer> double_it = x -> x * 2;
int result = double_it.apply(5); // 10

// Используется в Stream.reduce()
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int product = numbers.stream()
    .reduce(1, (a, b) -> a * b); // 120

BinaryOperator — две переменные, тот же тип

// BinaryOperator<T> = BiFunction<T, T, T>
BinaryOperator<Integer> multiply = (a, b) -> a * b;
int result = multiply.apply(5, 4); // 20

Практические примеры

Обработка коллекций

public class DataProcessor {
    public <T, R> List<R> processData(List<T> data, Function<T, R> transformer) {
        return data.stream()
            .map(transformer)
            .collect(Collectors.toList());
    }
}

// Использование
List<String> numbers = Arrays.asList("1", "2", "3");
List<Integer> integers = new DataProcessor()
    .processData(numbers, Integer::parseInt); // [1, 2, 3]

Стратегия преобразования

public class FormatService {
    private Map<String, Function<Object, String>> formatters = new HashMap<>();
    
    public FormatService() {
        formatters.put("date", obj -> ((Date) obj).toString());
        formatters.put("number", obj -> String.format("%.2f", obj));
        formatters.put("text", Object::toString);
    }
    
    public String format(String type, Object value) {
        Function<Object, String> formatter = formatters.get(type);
        if (formatter == null) {
            return value.toString();
        }
        return formatter.apply(value);
    }
}

Кэширование результатов

public class MemoizedFunction<T, R> {
    private Function<T, R> function;
    private Map<T, R> cache = new HashMap<>();
    
    public MemoizedFunction(Function<T, R> function) {
        this.function = function;
    }
    
    public R apply(T input) {
        return cache.computeIfAbsent(input, function::apply);
    }
}

// Использование
Function<Integer, Integer> expensiveCalc = x -> x * x * x;
MemoizedFunction<Integer, Integer> cached = new MemoizedFunction<>(expensiveCalc);

int result1 = cached.apply(5); // Вычисляет
int result2 = cached.apply(5); // Берет из кэша

Pipeline обработки данных

public class Pipeline<T, R> {
    private List<Function<?, ?>> functions = new ArrayList<>();
    
    public <S> Pipeline<T, S> addStep(Function<?, S> function) {
        functions.add(function);
        return (Pipeline<T, S>) this;
    }
    
    @SuppressWarnings("unchecked")
    public R execute(T input) {
        Object result = input;
        for (Function<?, ?> func : functions) {
            result = ((Function<Object, Object>) func).apply(result);
        }
        return (R) result;
    }
}

// Использование
String result = new Pipeline<String, Integer>()
    .addStep(String::toUpperCase)
    .addStep(String::length)
    .execute("hello"); // 5

Отличия Function от других интерфейсов

// Supplier - без параметров, возвращает значение
Supplier<String> supplier = () -> "Hello";

// Consumer - принимает параметр, ничего не возвращает
Consumer<String> consumer = System.out::println;

// Predicate - принимает параметр, возвращает boolean
Predicate<Integer> isPositive = x -> x > 0;

// Function - принимает параметр, возвращает результат
Function<String, Integer> getLength = String::length;

Вывод

Function — это основной функциональный интерфейс для преобразования данных. Он используется повсеместно в Stream API, функциональном программировании и позволяет писать чистый, декларативный код. Благодаря методам andThen() и compose() можно легко создавать цепочки преобразований.

Что такое Function? | PrepBro