Java: Лямбда выражения

Author: Tatyana Milkina

1. Что такое лямбда?

Рассмотрим следующий код, который подсчитывает количество только компактных автомобилей:

   private int getCompactCarsNumber(Car[] cars) {
        int result = 0;
        for (Car car : cars) {
            if (car.getType().equals(CarTypes.COMPACT)) {
                result++;
            }
        }
        return result;
    }

 

Предположим, добавляется еще одна задача - подсчитать количество автомобилей, у которых стоимость более 20 000:

    private int getExpensiveCarsNumber(Car[] cars) {
        int result = 0;
        for (Car car : cars) {
            if (car.getCost() > 20000) {
                result++;
            }
        }
        return result;
    }

Примеры 1 и 2 по сути отличаются только одной строчкой, в которой задается критерий поиска. Изменим код таким образом, чтобы не было необходимости вводить новый метод каждый раз при добавлении нового критерия поиска:

public interface Searchable {
    boolean test(Car car);
}
public class CompactCarSearch implements Searchable {
    public boolean test(Car car) {
        return car.getType().equals(CarTypes.COMPACT);
    }
}
public class ExpensiveCarSearch implements Searchable {
    public boolean test(Car car) {
        return car.getCost() > 20000;
    }
}
public class CarExample2 {
    public static void main(String[] args) {
        Car[] cars = {
                new Car(CarTypes.COMPACT, 34000),
                new Car(CarTypes.SPORT, 44000),
                new Car(CarTypes.COMPACT, 14000),
                new Car(CarTypes.COMPACT, 10000),
        };

        CarDemo2 carDemo = new CarDemo2();
        System.out.println(carDemo.getCarsNumber(cars, new CompactCarSearch()));
        System.out.println(carDemo.getCarsNumber(cars, new ExpensiveCarSearch()));

        System.out.println(carDemo.getCarsNumber(cars, new Searchable() {
            @Override
            public boolean test(Car car) {
                return car.getType().equals(CarTypes.COMPACT);
            }
        }));
    }

    private int getCarsNumber(Car[] cars, Searchable s) {
        int result = 0;
        for (Car car : cars) {
            if (s.test(car)) {
                result++;
            }
        }
        return result;
    }
}

В классе CarDemo2 вместо

carDemo.getCarsNumber(cars, new Searchable() {
            @Override
            public boolean test(Car car) {
                return car.getType().equals(CarTypes.COMPACT);
            }
        })

можно использовать лямбда выражение:

carDemo.getCarsNumber(cars,
 (Car car) -> car.getType().equals(CarTypes.COMPACT));

2. Синтаксис лямбда выражения

Общая форма записи:

(параметры) -> (тело)

Например:

(Object arg1, Object arg2) -> arg1.equals(arg2);

Лямбда выражение содержит три части: список параметров, стрелочка, тело.

Рассмотрим некоторые правила написания лямбда выражений:

  • Лямбда выражение может содержать ноль и более входных параметров:
    (int a1, int a2) -> { return a1 - a2; } 
    (String s) -> { System.out.println(s); } 
    () -> 89;
  • Тип параметра может быть явно объявлен или выведен компилятором из значения параметра. Например:
    (String s) -> { System.out.println(s); }​
    Можно переписать так:
    (s) -> { System.out.println(s); }​
  • Если параметров нет или их больше одного, скобки необходимы:
    (a1, a2) -> return a1 + a2;
    (int a1, int a2) -> return a1 + a2;
    () -> 42;​
  • Нет необходимости объявлять один параметр в скобках, но в этом случае нельзя явно указать тип параметра:
    a1 -> return 2 * a1​
  • Тело лямбда выражения может содержать ноль и более выражений.
  • Нет необходимости использовать фигурные скобки и ключевое слово return, если тело состоит из одного выражения. 
    () -> 4;
    (int a) -> a*6;​
  • Если тело содержит более одного выражения, фигурные скобки и ключевое слово return необходимы.
    () -> {
         System.out.println("Hi");
         return 4;
    }
    (int a) -> {
         System.out.println(a);
         return a*6;
    }​
  • Если ключевое слово return отсутствует, возвращаемый тип может быть void.
    () -> System.out.println("Hi");
    () -> {
         System.out.println("Hi");
         return;
    }​
Читайте также:
Комментарии
Wild_Wolf
Jan 21, 2019
CarDemo2 carDemo = new CarDemo2(); Что за класс CarDemo2?
milkina
Jan 22, 2019
Должно быть CarDemo carDemo = new CarDemo(); Исправлено.
sbnet@bk.ru
Nov 17, 2022
По-моему лямбда работают только как реализация абстрактных методов функциональных интерфейсов, но об этом ни слова((