Что такое лямбда-выражения (lambda functions) в Java?

Ответ

Лямбда-выражения в Java (с версии 8+) — это краткая форма записи анонимных функций, реализующих единственный абстрактный метод функционального интерфейса. Они позволяют писать более компактный и выразительный код, особенно в контексте Stream API и обработки коллекций.

Синтаксис: (параметры) -> { тело } или (параметры) -> выражение.

Примеры:

// 1. Сортировка списка с помощью лямбды
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.sort((a, b) -> a.compareTo(b));

// 2. Использование с Stream API
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Integer> squares = numbers.stream()
                               .map(n -> n * n) // Лямбда как Function
                               .collect(Collectors.toList()); // [1, 4, 9, 16, 25]

// 3. Запуск потока (Runnable)
new Thread(() -> System.out.println("Запуск из лямбды")).start();

Ключевые особенности:

  • Целевой тип: Тип лямбды определяется из контекста (ожидаемый функциональный интерфейс: Comparator, Predicate, Function, Consumer и т.д.).
  • Захват переменных: Лямбда может использовать effectively final переменные из окружающей области видимости (локальные переменные, которые не изменяются после инициализации).
  • Ссылки на методы: Часто могут быть заменены на более лаконичные ссылки на методы (String::compareTo, System.out::println).

Функциональные интерфейсы (пакет java.util.function) — основа для лямбд:

  • Predicate<T> — проверка условия (t -> t > 5).
  • Function<T,R> — преобразование объекта (s -> s.length()).
  • Consumer<T> — выполнение действия (obj -> System.out.println(obj)).
  • Supplier<T> — поставщик значения (() -> new Object()).

Ответ 18+ 🔞

Да ты посмотри, что эти умники в Java придумали! Лямбда-выражения, блядь. Ну, в рот меня чих-пых, раньше же писали эти анонимные классы на пол-экрана, а теперь — бац, и в одну строчку!

Представь, был у тебя Comparator, и писал ты его так, что мама не горюй. А теперь? (a, b) -> a.compareTo(b). И всё, пиздец! Красота, а не жизнь.

Синтаксис-то у них, ёпта, простой до безобразия: либо (параметры) -> { тело }, либо если одна команда — (параметры) -> выражение. Хуй с горы, и понятно.

Вот смотри, как они в деле:

// 1. Сортировка списка — раньше бы писал целый класс, а теперь...
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.sort((a, b) -> a.compareTo(b)); // И делов-то!

// 2. Stream API — это вообще отдельная песня, блядь. Магия.
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Integer> squares = numbers.stream()
                               .map(n -> n * n) // Взял число и нахуярил квадрат, всё
                               .collect(Collectors.toList()); // [1, 4, 9, 16, 25]

// 3. Поток запустить — вообще смешно стало
new Thread(() -> System.out.println("Запуск из лямбды")).start();

А теперь про подводные, блядь, камни, чтоб ты знал:

  • Целевой тип: Лямбда сама по себе — как беспризорник, блядь. Тип её определяется по тому, куда её суют. Ждёт от тебя Comparator — ну, значит, она и будет Comparator. Умная жопа, короче.
  • Захват переменных: Может она извне переменные брать, да. Но только те, что effectively final — то есть которые после создания не ебёшь. Иначе — компляйн-тайм, дружок.
  • Ссылки на методы: А ещё, сука, можно ещё короче! Вместо s -> s.length() написать String::length. Вообще ахуеть.

Основа всего этого цирка — функциональные интерфейсы (из java.util.function). Запомни этих уродцев, они везде лезут:

  • Predicate<T> — проверит что-то (t -> t > 5). Правда или нет, бля?
  • Function<T,R> — превратит одно в другое (s -> s.length()). Алхимик, ёпта.
  • Consumer<T> — сделает что-то с объектом, но ничего не вернёт (obj -> System.out.println(obj)). Просто потребитель, манда с ушами.
  • Supplier<T> — ничего не принимает, но что-то выдаёт (() -> new Object()). Как баба на сносях, только без истерик.

Вот и вся магия. Сначала охуеешь, а потом такой: "Да как же я раньше без этого жил, блядь?". Главное — не переборщить, а то код такой напишешь, что сам через неделю разбираться не захочешь.