Ответ
Лямбда-выражение — это краткий синтаксис для реализации функционального интерфейса (интерфейса с одним абстрактным методом). Оно позволяет передавать код как данные.
Синтаксис: (параметры) -> выражение или (параметры) -> { операторы; }
Пример: Замена анонимного класса
// До Java 8: анонимный класс
Runnable oldRunnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello from anonymous class");
}
};
// С лямбдой
Runnable newRunnable = () -> System.out.println("Hello from lambda");
Ключевые особенности:
- Типизация: Компилятор выводит типы параметров из контекста (контекст целевого типа).
- Доступ к переменным: Может захватывать
finalилиeffectively finalпеременные из окружающей области видимости. - Область видимости: Не создает новую область видимости для
thisиsuper— они ссылаются на enclosing-класс.
Практическое использование с Stream API:
List<String> names = Arrays.asList("Anna", "Bob", "John");
// Фильтрация с помощью лямбды
List<String> filtered = names.stream()
.filter(name -> name.startsWith("A")) // Предикат
.map(String::toUpperCase) // Ссылка на метод
.collect(Collectors.toList()); // ["ANNA"] Ответ 18+ 🔞
А, лямбды, ёпта! Ну это ж просто пиздец как удобно, если разобраться. Смотри, вот раньше-то, блядь, как было: хотел ты кусочек кода передать — писал целый анонимный класс, этот цирк с конями, на три строчки кода — десять строчек объявлений! Прям волнение ебать, как вспомнишь.
А теперь — красота, блядь. Взял и написал (параметры) -> выражение. Всё, пиздец. Компилятор сам, хитрая жопа, догадается, что ты от него хочешь.
Вот смотри, как раньше мучались:
// Это ж пиздец какой овердохуища код, блядь!
Runnable oldRunnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello from anonymous class");
}
};
А теперь, внатуре:
// Ёбушки-воробушки, одна строчка!
Runnable newRunnable = () -> System.out.println("Hello from lambda");
Чувак, ты представляешь? Всю эту хуйню с new, @Override — нахуй выкинул! Просто стрелочка и поехали.
А главные фишки, блядь, вот какие:
- Типы. Ты можешь их даже не писать, компилятор и так всё видит. Он же не слепой, сука. Сам выведет из контекста, что к чему.
- Переменные снаружи. Можешь ловить переменные извне, но только если они
finalили effectively final (то есть не меняются, блядь). Как поймал — так и пользуешься. thisиsuper. Вот тут внимание, ёпта! Они внутри лямбды ссылаются на внешний класс, а не на саму лямбду. Не создаётся новый объект, поэтому и путаницы нет.
А где это всё, блядь, реально пригождается? Да везде, сука! Особенно с этими вашими Stream API, которые всех задолбали, но они охуенные.
Смотри, был у тебя список имён:
List<String> names = Arrays.asList("Anna", "Bob", "John");
Хочешь отфильтровать только тех, кто на "A" начинается, да ещё и большими буквами сделать? Раньше бы циклы писал, итераторы... Пиздец. А сейчас:
List<String> filtered = names.stream()
.filter(name -> name.startsWith("A")) // Вот она, лямбда-проверка!
.map(String::toUpperCase) // А это ссылка на метод, тоже прикольная штука
.collect(Collectors.toList()); // И собираем обратно
// Получится ["ANNA"], блядь!
Короче, лямбды — это как взять и выкинуть из кода тонну ненужного строительного мусора. Остаётся только суть, чистая логика. Сначала, конечно, мозг ебёт, привыкнуть надо. Но как втянешься — обратно уже не захочешь, в рот меня чих-пых!