lambda

Wu Jun 2020-01-03 00:43:49
Categories: > > Tags:

@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 方法引用

:: 操作符表示直接传入一个方法作为方法体。

:: 操作符的用法:

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 个部分:

  1. 一个代码块
  2. 参数
  3. 自由变量的值,指非参数且不再代码中定义的变量。
    • 只能引用不会改变的变量。

6 处理 Lambda 表达式

使用 lambda 表达式的重点是延迟执行:

7 再谈 Comparators