Java8 之 Lambda

来源:互联网 发布:改视频的软件 编辑:程序博客网 时间:2024/06/06 01:50

函数接口

函数接口是只有一个抽象方法的的接口,用作 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。

方法引用中,调用的方法后面没有跟上一对括号

原创粉丝点击