背景
带有高效运行时编译器的Java虚拟机(JVM)的出现, 大多数程序跑在功能强大的多核CPU上。程序员可以将更多的精力放在编写干净、易于维护的代码上。Java对于大型数据集合欠缺高效的并行操作,为了编写批量处理数据的并行类库,Java增加了Lambda表达式。
函数式编程的核心是:在思考问题时,使用不可变值和函数,函数堆一个值进行处理,映射成另一个值。
Lambda表达式
示例代码:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.print("button clicked");
}
});
button.addActionListener(event->System.out.println("button clicked"));
与传入一个实现某接口的对象不同,我们传入一个代码块,一个没有名字的函数。event是参数名,和上面匿名类是同一个参数。将参数和Lambda表达式分开,而主体是用户点击按钮时会运行的一些代码。javac会根据上下文(addActionListener方法的签名)在后台推断出参数event的类型。
// ()表示不包含参数,表达式实现了Runnable接口,该接口只有一个run方法
// 没有参数,返回值是void
Runnable noArguments = () -> System.out.println("Hello Word!");
// 包含一个参数,可省略()
ActionListener oneArgument = event -> System.out.println("button clicked");
// Lambda表达式主体可以是一个代码块,使用{}括起来
// 可以用返回或抛出异常或退出
Runnable multiStatement = () -> {
System.out.print("Hello");
System.out.print(" World")
}
// 创建一个函数,用来计算两个数字相加的结果
BinaryOperator<Long> add = (x, y) -> x + y;
// 可以声明参数的类型,用小括号将参数括起来
BinaryOperator<long> addExplicit = (Long x, Long y) -> x + y;
目标类型: Lambda表达式所在上下文环境的类型。比如,将Lamabda表达式复制给一个局部变量,或者传递给一个方法做参数,局部变量或者方法参数的类型就是Lambda表达式的目标类型。Lambda表达式的类型依赖于上下文环境,由编译器推断出来。
引用值,而不是变量
String name = getUserName();
button.addActionListener(event -> System.out.println("hi" + name));
name为final,多次赋值,编译将会报错:”Lambda表达式中引用的局部变量必须是final或者既成事实的final变量”。
Lambda表达式也被称为闭包,未赋值的变量与周围的环境隔离起来,进而绑定到一个特定的值。