Ответ
Лямбда-выражение (лямбда) в Java — это краткая форма записи анонимной функции, реализующей метод функционального интерфейса (интерфейса с одним абстрактным методом). Введены в Java 8 для поддержки функционального программирования.
Синтаксис: (параметры) -> { тело выражения } или (параметры) -> выражение.
Простой пример:
// Без лямбды (анонимный класс)
Runnable oldRunnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};
// С лямбдой
Runnable newRunnable = () -> System.out.println("Hello");
Примеры с разными функциональными интерфейсами:
// Predicate<T> - проверяет условие
Predicate<String> isEmpty = s -> s == null || s.trim().isEmpty();
boolean test = isEmpty.test(""); // true
// Function<T,R> - преобразует объект
Function<String, Integer> stringToLength = str -> str.length();
int len = stringToLength.apply("Java"); // 4
// Consumer<T> - потребляет объект (выполняет действие)
Consumer<String> printer = message -> System.out.println("Log: " + message);
printer.accept("Test"); // Вывод: Log: Test
// Supplier<T> - поставляет объект
Supplier<Double> randomSupplier = () -> Math.random();
double val = randomSupplier.get();
Использование со Streams API (типичный кейс):
List<String> names = Arrays.asList("Anna", "Bob", "Alice");
// Фильтрация и преобразование с помощью лямбд
List<String> result = names.stream()
.filter(name -> name.startsWith("A")) // Predicate
.map(String::toUpperCase) // Method reference (частный случай лямбды)
.collect(Collectors.toList()); // ["ANNA", "ALICE"]
Ключевые особенности:
- Позволяют писать более чистый и компактный код.
- Не создают новый объект .class файл (в отличие от анонимных классов), что эффективнее.
- Могут захватывать переменные из окружающего контекста (должны быть effectively final).
- Являются основой для Streams API и многих современных Java-фреймворков.
Ответ 18+ 🔞
Да ты посмотри, что эти умники в Java 8 придумали! Лямбды, блядь. Ну, а че, удобно, если честно. Раньше, сука, чтобы функцию как объект передать, надо было анонимный класс городить, строчек на десять, а теперь — раз, и в одну строку.
Лямбда, если по-простому, — это короткий способ написать кусок кода, который делает одно действие. Типа функции, но без лишнего официоза. Работает только с функциональными интерфейсами — это такие интерфейсы, где всего один абстрактный метод. Ну, типа Runnable, Comparator и прочая хуйня.
Как выглядит? Да элементарно: (параметры) -> { тело } или даже (параметры) -> выражение.
Вот смотри, как было и как стало:
// Раньше, блядь, вот эта поебень:
Runnable oldRunnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};
// А теперь, ёпта, красота:
Runnable newRunnable = () -> System.out.println("Hello");
Чувствуешь разницу? Как будто гора с плеч свалилась, ебать мои старые костыли.
А вот ещё примерчики, чтобы въехать:
// Predicate<T> — проверяет что-то, типа фильтра
Predicate<String> isEmpty = s -> s == null || s.trim().isEmpty();
boolean test = isEmpty.test(""); // true, ну ясен пень, строка пустая
// Function<T,R> — берёт один объект, выдаёт другой
Function<String, Integer> stringToLength = str -> str.length();
int len = stringToLength.apply("Java"); // 4, всё верно
// Consumer<T> — делает что-то с объектом, типа съедает его
Consumer<String> printer = message -> System.out.println("Log: " + message);
printer.accept("Test"); // Выведет в консоль эту хуйню
// Supplier<T> — просто поставляет что-то, типа фабрика
Supplier<Double> randomSupplier = () -> Math.random();
double val = randomSupplier.get(); // Случайное число, вот и вся магия
А самое охуенное — это когда со Streams API используешь. Вот тут они реально раскрываются:
List<String> names = Arrays.asList("Anna", "Bob", "Alice");
// Отфильтруем имена на "A" и сделаем их большими буквами
List<String> result = names.stream()
.filter(name -> name.startsWith("A")) // Вот она, лямбда-проверка
.map(String::toUpperCase) // А это method reference, родственник лямбды
.collect(Collectors.toList()); // И собираем обратно в список
// Получится ["ANNA", "ALICE"]
Что в сухом остатке, а?
- Код становится короче и читабельнее, пиздец как.
- Не создают кучу лишних
.classфайлов, как анонимные классы, так что эффективнее. - Могут пользоваться переменными снаружи, но только если те фактически финальные (не меняются).
- Это, блядь, фундамент для всего современного в Java: Streams, Optional, всякие реактивные штуки. Без них теперь никуда, хитрая жопа.
В общем, вещь полезная. Сначала мозг ломается, а потом привыкаешь и без них как без рук.