1. Что такое лямбда
- Функциональное программирование? Анонимный внутренний класс? лаконичный?
- Возникший из академических кругов λ, он в основном представляет собой параметризацию поведения, упрощенный внутренний класс и широко используется в функциональном интерфейсе.
2. Зачем изучать лямбда?
- Не спрашивайте почему, управляющий фабрики мой двоюродный брат.
- Эта статья позволит вам научиться использовать лямбда-выражения полностью, независимо от того, где вы можете ()->{} немного.
3. лямбда-синтаксис
- полное лямбда-выражение
(Type1 param1,Type2 param2,Type3 params)->{
statement1;
statement2;
....
return data;
}
1. ()->{}, лямбда-параметры, стрелки и лямбда-тела обязательны
2. Тип параметра можно не указывать, и он вообще не указывается
3. Если в теле лямбды есть только один оператор, вы можете опустить фигурные скобки, return и завершающую точку с запятой.
4. Ссылки на методы можно использовать как лямбда-выражения.
лямбда без параметров
- Более продвинутые, чем анонимные внутренние классы, имя интерфейса и имя функции опущены.
- Тело лямбды состоит только из одной строки, и {} можно опустить.
параметризованная лямбда
- Много раз идеи можно оптимизировать, но. . . В представленной кодовой базе все еще есть куча идейных советов, выделенных серым цветом.
4. Функциональный интерфейс
- Основой для возможности использования лямбды является функциональный интерфейс, то есть интерфейс только с одним абстрактным методом внутри, а не просто с одним методом.
- Вывод типа лямбда-выражений также связан с функциональными интерфейсами, и компилятор может вывести типы параметров на основе контекстной информации.
Несколько типовых функциональных интерфейсов
1. Бифункция
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t, U u) -> after.apply(apply(t, u));
}
}
1. Этот функциональный интерфейс активно используется в потоке java 8.
2. Есть 2 метода, только 1 абстрактный метод
3. Абстрактный метод apply принимает два параметра, тип — T, U, а возвращаемое значение — R.
4. Функциональный интерфейс BiFunction третьего параметра get() ниже, поэтому вы можете передать лямбду, соответствующую спецификации функционального интерфейса, при вызове get(). Что касается параметра 1 и параметра 2, как работать, работать и шифровать. . . Зависит от вашего лямбда-тела.
2. Потребитель
- Функция потребления, возвращаемое значение недействительно.
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
- Возвращаемое значение недействительно, поэтому обычно используются его побочные эффекты.
3. Предикат
- Проверка утверждения/условия, определяет абстрактный метод, должен иметь 1 входной параметр, возвращаемое значение логическое.
- Наиболее часто используемый filter() в потоке может образовывать цепочку вызовов предикатов.
//以下都可以做一个Predicate的lambda
1、(s)->s.length()>0;
2、(v)->v > 100;
3、(o)->o.startWith("a");
4. Поставщик
- Ввод не требуется, вывод T. Подобно контейнеру, вызов get возвращает объект.
Supplier<Integer> supplier = new Supplier<Integer>() {
@Override
public Integer get() {
//返回一个随机值
return new Random().nextInt();
}
};
System.out.println(supplier.get());
System.out.println(supplier.get());
ссылка на метод
- Проще говоря, он позволяет повторно использовать существующие определения методов и передавать их как лямбда-выражения, используя :: для их обозначения. Есть три основные категории.
- Основной момент: сигнатура функции должна быть согласованной, то есть тип параметра, количество параметров, тип возвращаемого значения или пустота.
1. Ссылка на метод статического метода
- Статические методы действуют на объекты.
public static void main(String[] args) {
List<String> list = Lists.newArrayList("1","2","3","4");
List<Integer> collect1 = list.stream().map(v -> Integer.parseInt(v))
.collect(Collectors.toList());
List<Integer> collect2 = list.stream().map(Integer::parseInt)
.collect(Collectors.toList());
}
2. Ссылка на метод экземпляра любого типа.
1. Этот произвольный тип обычно относится к типу параметра вашей лямбды.
2. Если следующим входным параметром является v, вызов v.length может записать тип v String::length.
public static void main(String[] args) {
List<String> list = Lists
.newArrayList("hello", "how", "are", "you", "i", "am", "fine", "thank", "you", "and",
"you");
Set<Integer> collect = list.stream().map(v -> v.length()).collect(Collectors.toSet());
Set<Integer> collect1 = list.stream().map(String::length).collect(Collectors.toSet());
System.out.println(collect);
System.out.println(collect1);
}
3. Ссылка метода на метод существующего объекта
- Аналогично пункту 2 выше, без подробностей.
V. Резюме
- В основном представляет лямбда-выражения и функциональные интерфейсы.
- Суть использования функционального интерфейса состоит в том, чтобы получить правильную сигнатуру функции, передать лямбду, соответствующую условной сигнатуре, и вы можете спровоцировать ()->{}.