Lambda初步

什么是Lambda?Lambda是λ,希腊字母表中排序第十一位的字母。当你在使用IDEA书写Lambda表达式的时候,左侧会有λ的提示:这里写图片描述,它也是java8的新特性:不再使用传统的匿名对象的方式,而使用其更为简洁的语法。那么具体应该怎么使用呢

第一个Lambda表达式

我们先看看什么是Lambda表达式。举一个最简单的例子
我们一般写点击事件是这样的

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {}
});

一个点击事件写了这么多行,都不知道重点是什么,这样就凸显Lambda简洁的优势了

button.setOnClickListener(v -> {});

如果是第一次接触到Lambda,恐怕会丈二和尚摸不着头脑,我们这边简单的解释一下:这里的v就是上面onClick中的View对象,大括号中的就是主体部分,他们之间用->分开

辨别Lambda表达式

除了刚才演示的表现形式以外,还有多种变体,我们简单的举几个例子

  • . 不包含参数,并且返回值为void
new Thread(()->{}).start();
  • . 之前演示的,一个参数,并且主体为一个表达式
button.setOnClickListener(v -> Log.d("tag", "click"));
  • . 一个参数,并且主体为一段代码块。只有一行代码的表达式可以使用大括号也可以不使用,但是一段代码块的话就一定要使用大括号
button.setOnClickListener(v -> {
    Log.d("tag", "click");
    Log.d("tag", "click");
}});
  • . 多个参数的方法,你既可以显示声明变量参数类型,也可以啥都不写依靠编译器推断得出。如果显示声明,那么就需要用括号将参数括起来
listview.setOnitemClickListener((parent, view, position, id) -> {})
listview.setOnitemClickListener((AdapterView<?> parent, View view, int position, long id) -> {})

这两种写法是等价的

函数式接口

函数接口是只有一个抽象方法的接口,这点一定要搞清楚,只有符合上述条件,才可以用作Lambda表达式类型,2个3个抽象方法的接口是不能玩的

首先列举以下6种常见的函数式接口

接口参数返回类型
FunctionTR
PredicateTboolean
SupplierNoneT
UnaryOperatorTT
ConsumerTvoid
BinaryOperator(T, T)T

OK,我看第一遍的时候愣是看不懂这个里面想传达的意思,然后写着写着才明白,依然举例

我们使用Function来说明。

Function<Integer, String> function3=integer -> ""+integer;
System.out.println(function3.apply(111));

这个方法的目的在于将Integer转成String。入参泛型为Integer,返回值泛型为String。

OK看不明白不要紧,我们转成常见的方式来看,写一个Integer转String的接口,我们会定义成这种形式

public interface ConvertListener {
    String convert(Integer integer);
}
ConvertListener convertListener1=new ConvertListener() {
    @Override
    public String convert(Integer integer) {
        return ""+integer;
    }
};
convertListener1.convert(111);

OK,就是这么简单

方法与构造函数引用

如果方法体知识简单的函数引用则可以直接使用::引用,这样可以让我们的代码更加简洁。
看一个例子:

Function<Integer, String> function2=String::valueOf;
function2.apply(3);

::左边的对象调用符号右边的方法

这里我只是想简单说明一下,因为这段代码完全不能体现他的优越性

现在我们开始展开演示

首先是一个ConvertClass类

public class ConvertClass {
    String startsWith(Integer integer) {
        return String.valueOf(integer);
    }

    public static String startsStaticWith(Integer integer) {
        return String.valueOf(integer);
    }
}
  • Lambda访问构造方法

我们得再定义一个抽象接口以使用ConvertClass的构造方法

@FunctionalInterface
interface ConvertClassFactory<T extends ConvertClass> {
    T create();
}

再次强调ConvertClassFactory只能有一个抽象方法

最后看看如何使用

ConvertClassFactory factory=ConvertClass::new;
ConvertClass convertClass=factory.create();

通过”类名::new”的方式获得构造的引用,最后通过create调用构造方法,编译系统会自动识别调用ConvertClass的哪个构造方法。

  • Lambda访问静态方法

刚才我们已经拿到了ConvertClass的对象convertClass,下面我们来看看如何调用静态方法startsStaticWith

ConvertListener listener2=ConvertClass::startsStaticWith;
String re2=listener2.convert(101);
System.out.println(re2);

直接就是类::方法名直接使用即可

  • Lambda访问对象的方法
ConvertListener listener=convertClass::startsWith;
String re1=listener.convert(100);
System.out.println(re1);

其实区别并不大,主要是用已生成的对象去直接调用方法而已

Lambda访问外部局部变量

还记得我们在setOnItemClickListener里面如果遇到内部类使用position时,前面要加一个final来修饰?在Lambda中,这个final可以被省略,但是你依然不可以为了赋值,它实际上依然是final

参考链接

JAVA8中Lambda和Stream
Java 8 Lambda表达式

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页