Комментарии (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() можно легко создавать цепочки преобразований.