几个基本概念
1.函数式接口
只定义一个抽象方法的接口。函数式接口一般会加上注解@FunctionalInterface
e.g
public interface Comparator<T> {
int compare(T o1, T o2);
}
pubilc void Runnable() {
run();
}
2.函数描述符
函数式接口的抽象方法的签名基本上就是Lambda表达式的签名,我们将这种抽象方法叫做函数描述符。例如,Runnable接口可以看作一个什么也不接受什么也不返回的而函数的签名,因为它只有一个叫做run的抽象方法。
3.常用函数式接口
函数式接口 | 函数描述符 | 使用案例 | Lambda的例子 | 对应的函数式接口 |
Predicate<T> | T -> boolean | 布尔表达式 | (List<String> list) -> list.isEmpty()) | Predicate<T> |
Suppllier<T> | ()->T | 创建对象 | () -> new Apple(10) | Suppllier<T> |
Consumer<T> | T->void | 消费一个对象 | (Applr a)) -> System.out.println(a.getWeight()) | Consumer<T> |
Function<T,R> | T->R | 从一个对象中选择/提取 | (String s) -> s.length() | Function<T,R> |
BinaryOperator<T> | (T,T)->T | 合并两个值 | (int a, int b) -> a*b | BinaryOperator<T> |
Comparator<T> | (T,T)->T | 比较两个对象 | (Apple a1, Apple a2) -> a1.getWeight().CompareTo(a2.getWeight()) | Comparator<Apple> |
lambda表达式的语法格式如下:
(parameters) -> expression或(parameters) ->{ statements; }
以下是lambda表达式的重要特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
4.方法引用 目标引用::方法名称
- 指向静态方法的方法引用,例如,Integer.parseInt();
- 指向任意类型实例方法的方法引用,在引用一个对象的方法,该对象是lambda的参数
- 指向现有对象的实例方法,调用已经存在的外部对象的方法
简单的lambda表达式的使用
1.利用lambda表达式对列表进行迭代
控制台:
也可以用:list1.forEach(System.out::println);
2.使用lambda表达式替代匿名内部类
() -> {}替代了匿名内部类
3.使用lambda表达式和函数式接口Predicate
java8新增了一个包,叫做 java.util.function,接口里面包含了很多类,用来支持函数式编程,其中有一个接口就是Predicate,用Perdicate可以用来过滤,下面我们展示一下过滤集合的相关数据
直接在filter中写过滤条件或者传入一个Predicate都行,有人或许说既然可以直接写过滤条件,用Predicate是不是有点多余了,不不,继续看,你就知道为什么要用Predicate了
4.Predicate之多个过滤条件
若需要多个过滤条件,而不是单单的一个过滤条件,那么怎么实现呢。Predicate提供类似于逻辑操作符AND和OR的方法,名字叫做and()和or(),用于将传入 filter() 方法的条件合并起来。
and()将满足条件的结果查询出来,or()将满足其中任意一个条件的结果查询出来
注:lambda表达式有个限制,那就是只能引用 final 或 final 局部变量,这就是说不能在lambda内部修改定义在域外的变量。
编译的时候就报错,注意,可以访问但是不能修改