@since 1.8
1 语法
参数,箭头(->)以及一个表达式。
(String first, String second) ->first.length() - second.length()
没有参数也要提供空括号,就像无参数方法一样。
() -> { for (int i = 100; i >= 0; i--) System.out.println(i); }
如果可以推导出参数类型,则可以忽略类型。
Comparator<String> comp
= (first, second) // Same as (String first, String second)
-> first.length() - second.length();
如果方法只有一个参数,而且参数类型可以推导出,这个连小括号都省略了
ActionListener listener = event ->
System.out.println("The time is " + new Date());
无需指定lambda表达式的返回类型。返回类型总会由上下文推导得出。
(String first, String second) ->first.length() - second.length()
2 函数式接口
对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式。
Arrays.sort(planets, (first, second) -> first.length() - second.length());
Arrays.sort() 方法的第二个参数要求是一个实现 Comparaor 接口的实例。Comparaor 就是只有一个方法的接口。
Lambda 表达式不是对象,而是函数。或者更具体的说,上面的 sort 方法想要传入的参数并不是那个 Comparator 对象的实例,而是其 compare 方法的计算方法。
在 Java 中对 lambda 表达式能做的也只是转换为函数式接口。想要用 lambda 表达式做某些处理,就为它建立一个特定的函数式接口。
3 方法引用
::
操作符表示直接传入一个方法作为方法体。
System.out::println
等价于event -> System.out.println(event)
::
操作符的用法:
- 特定对象的方法引用:instance::method
- 静态方法引用:Class::static_method
- 特定类的任意对象的方法引用:Class::method
- 这个的意思是把第一个参数当作实例,例:String::compareTo的意思是(x,y) -> x.compareTo(y)
- 同样的,this 和 super 关键字也同样能用。
4 构造器引用
Class::new,或者更一般的 Class< T >::new。请注意构造器没有参数。
与方法引用类似,只是用 new 代替方法名称。
哪一个构造器取决于上下文。
ArrayList<String> names = . . .;
Stream<Person> stream = names.stream().map(Person::new);//等同于调用 new Person(String)
List<Person> people = stream.collect(Collectors.toList());
数组
int[]::new 参数数组的长度,等价于 x->new int[x].
数组构造器引用可以克服对泛型数组的限制。
Object[] people = stream.toArray();//返回一个Object[]
Person[] people = stream.toArray(Person[]::new);//返回一个Person[]
5 变量作用域
lambda 表达式由 3 个部分:
- 一个代码块
- 参数
- 自由变量的值,指非参数且不再代码中定义的变量。
- 只能引用不会改变的变量。
- 闭包:代码块和自由变量。lambda 表达式就是闭包。
- this:lambda表达式中 this 指创建这个 lambda 表达式的方法的 this。
6 处理 Lambda 表达式
使用 lambda 表达式的重点是延迟执行:
- 要分离线程时候使用
- 在多个时间要运行
- 在算法的指定点运行
- 某些事件发生时运行
- 有必要才运行