Урок 15

Лямбда

1. Для чего используется Лямбда-выражение

Рассмотрим следующий код:

Пример 1.  Поиск компактных автомобилей

Метод отфильтровывает о возвращает коллекцию, содержащую только компактные автомобили:

    List<Car> findCompactCars(List<Car> cars) {
        List<Car> compactCars = new ArrayList<>();
        for (Car car : cars) {
            if (car.getType().equals(CarTypes.COMPACT)) {
                compactCars.add(car);
            }
        }
        return compactCars;
    }

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

Пример 2.  Поиск дорогих автомобилей

   List<Car> findExpensiveCars(List<Car> cars) {
        List<Car> twentyKCars = new ArrayList<>();
        for (Car car : cars) {
            if (car.getCost() > 20000) {
                twentyKCars.add(car);
            }
        }
        return twentyKCars;
    }

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

Пример 3.  Поиск автомобилей по разным критериям

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 TwentyKCarSearch implements Searchable {
    public boolean test(Car car) {
        return car.getCost() > 20000;
    }
}
public class CarDemo {
    public static void main(String[] args) {
        List<Car> cars = new ArrayList<>();
        cars.add(new Car(CarTypes.COMPACT, 34000));
        cars.add(new Car(CarTypes.SPORT, 44000));
        cars.add(new Car(CarTypes.COMPACT, 14000));
        cars.add(new Car(CarTypes.COMPACT, 10000));

        CarDemo2 carDemo = new CarDemo2();
        System.out.println(carDemo.findCars(cars, new CompactCarSearch()));
        System.out.println(carDemo.findCars(cars, new TwentyKCarSearch()));

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

    private List<Car> findCars(List<Car> cars, Searchable s) {
        List<Car> searchedCars = new ArrayList<>();
        for (Car car : cars) {
            if (s.test(car)) {
                searchedCars.add(car);
            }
        }
        return searchedCars;
    }
}

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

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

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

carDemo.findCars(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;
    }​



0 comments
Leave your comment: