您的位置:首页 > 编程语言 > Java开发

Java8 之 Lambda

2017-08-25 12:47 148 查看

函数接口

函数接口是只有一个抽象方法的的接口,用作 Lambda 表达式类型。

例如 View 的 onClickListener 接口就是函数接口

public interface OnClickListener {
void onClick(View view);
}


使用图形可以清晰表达函数接口



为 Button 设置监听事件

mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "Hello Lambda");
}
});


匿名内部类的设计是为了方便程序员,但是也造成了代码的冗余和可读性差的问题。

Lambda 表达式

把上面代码用 Lambda 表达式转化如下

mButton.setOnClickListener(view -> Log.d(TAG, "Hello Lambda"));


Lambda 表达式为
view -> Log.d(TAG, "Hello Lambda")
,这个意思就很明确了,用参数 view 来输出一条 Log 信息,所以 Lambda 表达式简洁地表达了一种行为。

view 为 Lambda 表达式参数,Log.d() 为 Lambda 表达式的主体。 同时需要注意,如果主体只有一行代码,不需要在后面加上分号。

Lambda 表达式类型推断

Java 是静态语言, 然而上面的例子中的 Lambda 表达式中的参数 view 并没有声明类型,这是由 javac 根据上下文推断出来的,就如同 Java7 中的类型推断

HashMap<String, String> map = new HashMap<>();


Lambda 表达式返回值

函数接口 Predicate 如下

public interface Predicate<T> {
boolean test(T var1);
}


用这个接口来进行一个过滤操作

List<Integer> list = Stream
.of(1, 2, 3)
.filter(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return 1 > 2;
}
})
.collect(Collectors.toList());


然后转化为 Lambda 表达式

List<Integer> list = Stream
.of(1, 2, 3)
.filter(integer -> 1 > 2)
.collect(Collectors.toList());


注意到 test() 方法的返回值 boolean,然而在 Lambda 表达式的主体中并没有明确用 return 来返回,也就是说,Lambda 表达式自动取了主体的(1 > 2) 的结果。

再来看一个例子

mButton.setOnClickListener(view -> view.getId());


这个是不是也很奇怪,onClickListener 接口中的 onClick() 方法的返回是 void,而 Lambda 表达式主体的返回是 int,而这个时候 Lambda 表达式根据 onClick() 返回值,并不会自动获取 view.getId() 的返回值。

Lambda 表达式形式

无参 Lambda 表达式

new Thread(() -> Log.d(TAG, "run")).start();


代码很简单,创建一个线程并运行。 这里的 Lambda 表达式是无参的,用一对括号表示无参。

有参 Lambda 表达式

前面例子中演示了一个参数的 Lambda 表达,再看看多参的情况

Stream.of(1, 2, 3).reduce(new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer integer1, Integer integer2) {
return integer1 + integer2;
}
});


BinaryOperator 也是一个函数接口,apply() 方法有两个参数,转化为 Lambda 表达式如下

Stream.of(1, 2, 3).reduce((integer1, integer2) -> integer1 + integer2);


Lambda 表达式主体

Lambda 表达式主体不仅仅是一个表达式,还可以是一个代码块

mButton.setOnClickListener(view -> {
view.getId();
Log.d(TAG, "hello Lambda");
});


Lambda 表达式主体如果是代码块,每一个表达式后面都要带分号;

方法引用

Lambda 有一个常见的用法就是经常调用参数,例如

mButton.setOnClickListener(view -> view.getId());


由于这种 Lambda 用法比较普遍,所以 Java 8 为其提供一个简洁地语法,叫做方法引用。所以上面的 Lambda 表达式可以转化如下

mButton.setOnClickListener(View::getId);


方法引用的标准语法为 ClassName::methodName。

方法引用中,调用的方法后面没有跟上一对括号
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息