Java 8引入流机制和Lambda表达式之后,两者配合地可谓是天衣无缝,本来想看看Java流库有什么东西,可是全是Lambda表达式,晕死,看来得好好了解一下Lambda了!
函数式编程
在文献2中,作者由Swing中的ActionListener
来引入Lambda的概念。比如:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("button clicked");
}
});
这个语法是不知道从什么时候引入的Java匿名类,在上述代码里,它新创建了一个ActionListener
类,并重写了actionPerformed
的方法。实际上ActionListener。这个类只有这一个方法,目的就是让此类的使用者重写方法来完善按钮按下的具体动作。
像ActionListener
这种接口其实功能相当单一,其除了System.out…那行代码其他的全部可以通过接口声明由编译器自动推断。那么,这个模板代码是一个冗余的存在。Lambda的目的就是干掉它。哦,对了,ActionListener就是函数式接口,函数式接口简单说就是只有一个方法的接口。
那么接下来的代码可能大多数人都见过:
button.addActionListener(event->System.out.println("button clicked"));
解析一下它的结构,event是参数,->代表这是一个Lambda表达式,后面是逻辑语句,多上代码的话可以用{}
来包围。
那么event->System.out.println("button clicked")
这块代码其实就代替了以上的匿名内部类,并且返回的同样也是一个ActionListener
,因此可以是这个样子。
ActionListener listener=event->System.out.println("button clicked")
Lambda表达式是代码块,类型就是函数式接口,我之前看到过很多类似的函数式接口如Predicate,Consumer等,部分还应用到了泛型。
但是Lambda表达式在我初学时,根本就没有办法看。因为看不懂,不过现在我可以在脑海里构造这样一个映射:
event->System.out.println("button clicked")
==
new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("button clicked");
}
}
为了深入理解这一点,可以自己构造一个类似Comsumer等JDK内置函数式接口。
以我的英文名Oneslide Icyater为例
public interface Oneslide {
void callmyname();
}
这个接口只有一个方法,因此这个是个合法的函数式接口,接下来写个Main证明一下:
public class Main {
public static void main(String args[]) {
Oneslide icywater=()->{
System.out.println("oneslide icywater");
};
icywater.callmyname();
}
}
你会得到oneslide icywater这样的输出。可见,Lambda并非什么秘密武器,它只是一个语法糖。前面也说到会和泛型一起用,那么把上面例子变得再复杂一点:
public interface Oneslide<T> {
String callmyname(T target);
}
上面的接口有了返回值和泛型
public class Main {
public static void main(String args[]) {
Oneslide icywater=(name)->{
String returnName=(String)name+" icywater";
//简单输出一下吧,不然有点尴尬
System.out.println(returnName);
return returnName;
};
icywater.callmyname("oneslide");
}
}
虽然上面的例子是一个很挫地使用了泛型,但是能够充分证明其用法,那么剩下的可以利用
面向对象的概念对语法进行解释了,简化一下代码:
至于为什么引入Lambda呢?我猜大概是其写出来代码所表现出的简洁性超过其不易读的特点。
那么其应用于Stream库
String name="oneslide icywater";
System.out.println(name.chars().filter((w)->w>100).max());
如果你查看filter的声明你会发现Predicate,这里的(w)->w>100)
作为一个匿名的Predicate实现类。这几行语句的意思找到编码大于100且最大的字母。
相关链接
参考文献
- Mastering Lambdas: Java Programming in a Multicore World- Maurice Naftalin
- Java 8 Lambdas: Functional Programming For The Masses -Richard Warburton
- Core Java Volume II -10th edition