5.1 Lambda表达式
5.1.1 Lambda表达式初探
Lambda表达式,也可称为闭包,是Java 8最重要的新特性之一。Lambda允许把函数作为一个方法的参数使用。使用Lambda表达式可以使代码变得更加简洁紧凑。其实Lambda表达式的本质只是一个“语法糖”,由编译器推断并转换为常规的代码,因此可以使用更少的代码来实现同样的功能。
Lambda表达式的语法格式如下:
(parameters) -> expression (parameters) ->{ statements; }
Lambda表达式的一些重要特征如下。
• 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
• 可选的参数圆括号:当只有一个参数时,无须定义圆括号,但如果有多个参数则需要定义圆括号。
• 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
• 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值。
下面是Lambda表达式常见的书写方式:
// 不需要参数,返回值为 5 () -> 5 // 接收一个参数(数值类型),返回其2倍的值 x -> 2 * x // 接受两个参数(数值类型),并返回两者的差值 (x, y) -> x – y // 接收两个int型参数,返回两者的和 (int x, int y) -> x + y // 接受一个 string 对象,并在控制台打印,不返回任何值 (String s) -> System.out.print(s)
下面将通过案例展示Lambda表达式的使用:
运行测试代码得到如下测试结果:
100 + 50 = 150 100 - 50 = 50 100 x 50 = 5000 100 / 50 = 2
5.1.2 Lambda表达式作用域
可以直接在Lambda表达式中访问外层的局部变量,但在Lambda表达式内部不能修改定义在Lambda表达式外部的局部变量,否则会编译错误。Lambda表达式的局部变量可以不用声明为final,但是必须不可被后面的代码修改(即隐性的具有final的语义)。在Lambda表达式当中不允许声明一个与外部变量同名的参数或者局部变量。
如果将today = "2018/10/12"这一行代码取消注释,将会出现Variable used in lambda expression should be final or effectively final编译错误。如果将String myName = "Java"这一行代码取消注释,也会出现编译错误。
执行以上代码,得到执行结果如下:
Hello World !
5.1.3 在线程中使用Lambda表达式
下面通过案例代码将不使用Lambda表达式和使用Lambda表达式时的简洁代码进行对比:
执行测试代码,得到执行结果如下:
线程1 线程2
5.1.4 在集合中使用Lambda表达式
经常需要在集合中对集合中的元素进行排序。下面使用一个集合元素排序的案例对Lambda表达式的使用进行阐释。首先定义一个Person类,其中包含两个属性,姓名name和年龄age。
在测试代码中,对不使用Lambda表达式和使用Lambda表达式的场景进行对比。
执行测试代码,得到如下测试结果:
[张三:20, 李四:22, 王五:26] [王五:26, 李四:22, 张三:20] [张三:20, 李四:22, 王五:26]
5.1.5 在Stream中使用Lambda表达式
Stream是对集合的包装,通常和Lambda表达式一起使用。使用Lambda表达式可以支持许多操作,如map、filter、limit、sorted、count、min、max、sum和collect等等。在接下来的案例中,将使用Lambda表达式和Stream对Person集合进行排序。
在测试案例中,将personList对象转换为Stream对象,并配合Lambda表达式对其进行排序。执行代码,可得到如下测试结果:
[张三:24, 赵六:26, 王五:28, 赵七:30, 李四:32]