Java,Lambda表达式、方法引用和构造器引用

目录

一、Lambda表达式

语法格式:

格式一:无参数,无返回值。

格式二:要参数,无返回值。

格式三:数据类型可以省略,可以由编译器进行类型推断。

格式四:只有一个参数时,参数的小括号可以省略。

格式五:有两个及以上的参数,有多条执行语句,并且有返回值。

格式六:当l方法体只有一条语句时,大括号{}可以省略。如果只有一条return语句,则大括号{}和return一并省略。

函数式接口(FunctionalInterface)

四个基本的函数式接口:

Lambda表达式的总结:

二、方法引用

具体使用情况:

情况1:对象 :: 实例方法

情况2:类 :: 类方法(静态方法)

情况3:类 :: 实例方法

三、构造器引用:

四、数组引用:


一、Lambda表达式

Lambda是一个匿名函数,可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用其可以写出更灵活、简洁的代码。
Lambda表达式用于简写用接口的引用创建对象的操作( 需满足此接口中只有一个抽象方法,即此接口为函数式接口)。
Lambda表达式的使用的举例:
(o1,o2) -> Integer . compare (o1,o2);
Lambda表达式的格式:
-> :lambda操作符或箭头操作符
->左边的内容:lambda形参列表(对应着要重写的接口中的抽象方法中的形参列表)
->右边的内容:lambda体(对应着接口的实现类要重写的方法的方法体)
格式:lambda形参列表 -> lambda体 

语法格式:

格式一:无参数,无返回值。

以Runnable接口为例:
Runnable r1 = new Runnable()
{
    @Override
    public void run()
    {
        System.out.println("I love China");
    }
};

等同于:

Runnable r2 = () -> {
    System.out.println("I love China");
};

格式二:要参数,无返回值。

以Consumer接口为例:

Consumer<String> con1 = new Consumer<String>()
{
    @Override
    public void accept(String s)
    {
        System.out.println(s);
    }
};

等同于:

Consumer<String> con2 = (String s) -> {
    System.out.println(s);
};

格式三:数据类型可以省略,可以由编译器进行类型推断。

还是以Consumer接口为例:

Consumer<String> con1 = new Consumer<String>()
{
    @Override
    public void accept(String s)
    {
        System.out.println(s);
    }
};

等同于:

Consumer<String> con2 = (s) -> {
    System.out.println(s);
};

格式四:只有一个参数时,参数的小括号可以省略。

还是以Consumer接口为例:

Consumer<String> con1 = new Consumer<String>()
{
    @Override
    public void accept(String s)
    {
        System.out.println(s);
    }
};

等同于:

Consumer<String> con2 = s -> {
    System.out.println(s);
};

格式五:有两个及以上的参数,有多条执行语句,并且有返回值。

以Comparator接口为例:

Comparator<Integer> com1 = new Comparator<Integer>()
{
    @Override
    public int compare(Integer o1, Integer o2)
    {
        System.out.println(o1);
        System.out.println(o2);
        return Integer.compare(o1,o2);
    }
};

等同于:

Comparator<Integer> com2 = (o1,o2) -> {
    System.out.println(o1);
    System.out.println(o2);
    return Integer.compare(o1,o2);
};

格式六:当l方法体只有一条语句时,大括号{}可以省略。如果只有一条return语句,则大括号{}和return一并省略。

还是以Comparator接口为例:

Comparator<Integer> com1 = new Comparator<Integer>()
{
    @Override
    public int compare(Integer o1, Integer o2)
    {
        return Integer.compare(o1,o2);
    }
};

等同于:

Comparator<Integer> com2 = (o1,o2) -> Integer.compare(o1,o2);

Lambda表达式的本质:一方面,Lambda表达式作为接口的实现类的对象。另一方面,Lambda表达式是一个匿名方法。

函数式接口(FunctionalInterface)

如果接口中只有一个抽象方法,则此接口就称为函数式接口。

只有给函数式接口提供实现类的对象时,我们才可以使用Lambda表达式

API中函数式接口所在的包:java.util.function

四个基本的函数式接口:

函数式接口

称谓

参数类型

用途

Consumer<T>

消费型接口

T

对类型为T的对象应用操作,包含方法:void accept(T t)

Supplier<T>

供给型接口

返回类型为T的对象,包含方法:T get()

Function<T,R>

函数型接口

T

对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(Tt)

Predicate<T>

判断型接口

T

确定类型为T的对象是否满足某约束,并返回boolean值。包含方法:boolean test(T t)

Lambda表达式的总结:

->的左边:lambda形参列表,参数的类型都可以省略。如果形参只有一个,则括号( )也可以省略。

->的右边:lambda体,对应着重写的方法体。当方法体只有一条语句时,大括号{}可以省略。如果只有一条return语句,则大括号{}和return一并省略。

二、方法引用

使用举例:

以Comparable接口为例:

Comparator<Integer> com1 = new Comparator<Integer>()
{
    @Override
    public int compare(Integer o1, Integer o2)
    {
        return Integer.compare(o1,o2);
    }
};

等同于:

Comparator<Integer> com3 = Integer :: compare;

方法引用可以看作是基于lambda表达式的进一步刻画。当需要提供一个函数式接口的实例时,可以使用Lambda表达式。当满足一定条件的情况下,我们还可以使用方法引用或构造器引用替换lambda表达式。

方法引用作为了函数式接口的实例。

格式:类(或对象):: 方法名

具体使用情况:

情况1:对象 :: 实例方法

函数式接口中的抽象方法A,其匿名内部类的匿名对象的实现方法中,调用了某个对象O的某个方法B(非静态)的形参列表与返回值类型与抽象方法A的形参列表与返回值类型一致(可以满足自动装箱和自动拆箱,或满足多态性),可以用方法B对方法A替换、覆盖,便可以直接表示为 对象(对象O) :: 实例方法(方法B)。此替换覆盖即为方法引用。

以Consumer接口为例:(注:System.out是一个对象)

//匿名内部类的格式
Consumer<String> con1 = new Consumer<String>()
{
    @Override
    public void accept(String s)
    {
        System.out.println(s);
    }
};
//Lambda表达式的格式
Consumer<String> con2 = s -> System.out.println(s);
//方法引用的格式
Consumer<String> con3 = System.out::println;

以Supplier接口为例:

Person pp = new Person(12,"Tom");
//匿名内部类的格式
Supplier<String> sup1 = new Supplier<String>()
{
    @Override
    public String get()
    {
        return pp.getName();
    }
};
//Lambda表达式的格式
Supplier<String> sup2 = () -> pp.getName();
//方法引用的格式
Supplier<String> sup3 = pp :: getName;

情况2:类 :: 类方法(静态方法)

函数式接口中的抽象方法A,其匿名内部类的匿名对象的实现方法中,调用了某个类C的某个类方法B(静态方法)的形参列表与返回值类型与抽象方法A的形参列表与返回值类型一致(可以满足自动装箱和自动拆箱,或满足多态性),可以用方法B对方法A替换、覆盖,便可以直接表示为 类(类C) :: 实例方法(方法B)。

以Comparable接口为例:

//匿名内部类的格式
Comparator<Integer> com1 = new Comparator<Integer>()
{
    @Override
    public int compare(Integer o1, Integer o2)
    {
        return Integer.compare(o1,o2);
    }
};
//Lambda表达式的格式
Comparator<Integer> com2 = (o1, o2) -> Integer.compare(o1,o2);
//方法引用的格式
Comparator<Integer> com3 = Integer :: compare;

以Function接口为例:

//匿名内部类的格式
Function<Double,Long> fun1 = new Function<Double, Long>()
{
    @Override
    public Long apply(Double aDouble)
    {
        return Math.round(aDouble);
    }
};
//Lambda表达式的格式
Function<Double,Long> fun2 = aDouble -> Math.round(aDouble);
//方法引用的格式
Function<Double,Long> fun3 = Math :: round;

情况3:类 :: 实例方法

函数式接口中的抽象方法A,其匿名内部类的匿名对象的实现方法中,调用了某个对象O的某个方法B(非静态)的返回值类型与抽象方法A的返回值类型一致(可以满足自动装箱和自动拆箱,或满足多态性)。

同时,方法A中有n个参数,方法B中有n-1个参数,且抽象方法A的第一个参数作为方法B的调用者(即对象O),方法B的n-1个参数与方法A的第一个参数之后的n-1个参数一致(可以满足自动装箱和自动拆箱,或满足多态性),可以用方法B对方法A替换、覆盖,便可以直接表示为 类(对象O所在的类) :: 实例方法(方法B)。此替换覆盖即为方法引用。

比如,若A方法的参数依次为H、I、J、K类型的,B方法的参数依次应该为I、J、K类型的(或满足自动装箱和自动拆箱,或满足多态性)。

以Comparator接口为例:

//匿名内部类的格式
Comparator<String> com1 = new Comparator<String>()
{
    @Override
    public int compare(String s1, String s2)
    {
        return s1.compareTo(s2);
    }
};
//Lambda表达式的格式
Comparator<String> com2 = (s1,s2) -> s1.compareTo(s2);
//方法引用
Comparator<String> com3 = String :: compareTo;

以BiPredicate接口为例:

//匿名内部类的格式
BiPredicate<String,String> biPre1 = new BiPredicate<String, String>()
{
    @Override
    public boolean test(String s1, String s2)
    {
        return s1.equals(s2);
    }
};
//Lambda表达式的格式
BiPredicate<String,String> biPre2 = (s1,s2) -> s1.equals(s2);
//方法引用
BiPredicate<String,String> biPre3 = String :: equals;

三、构造器引用:

格式:类名 :: new

以Suppiler为例:

//匿名内部类的格式
Supplier<Person> sup1 = new Supplier<Person>()
{
    @Override
    public Person get()
    {
        return new Person();
    }
};
System.out.println(sup1.get());
//Lambda表达式的格式
Supplier<Person> sup2 = () -> new Person();
//构造器引用的格式
Supplier<Person> sup3 = Person :: new;

说明:

·调用了类名对应的类中的某一个确定的构造器

·具体调用的是与函数式接口中的抽象方法的形参列表一致(可以满足自动装箱和自动拆箱,或满足多态性)的形参列表的构造器。

以Function接口和BiFunction接口为例:

//匿名内部类的格式
Function<Integer,Person> func1 = new Function<Integer, Person>()
{
    @Override
    public Person apply(Integer integer)
    {
        return new Person(integer);
    }
};
//Lambda表达式的格式
Function<Integer,Person> func2 = integer -> new Person(integer);
//构造器引用
Function<Integer,Person> func3 = Person :: new;//调用的是参数为Integer类型的,由于自动拆箱,调用的是int类型的构造器


//匿名内部类的格式
BiFunction<Integer,String,Person> biF1 = new BiFunction<Integer, String, Person>()
{
    @Override
    public Person apply(Integer integer, String s)
    {
        return new Person(integer,s);
    }
};
//Lambda表达式的格式
BiFunction<Integer,String,Person> biF2 = (integer,s) -> new Person(integer,s);
//构造器引用的格式
BiFunction<Integer,String,Person> biF3 = Person :: new;

四、数组引用:

格式:数组名[ ] :: new

说明:数组引用里的数组的长度由方法的参数决定。

例:

//匿名内部类的格式
Function<Integer,Person[]> fu1 = new Function<Integer, Person[]>()
{
    @Override
    public Person[] apply(Integer integer)
    {
        return new Person[integer];
    }
};
//Lambda表达式的格式
Function<Integer,Person[]> fu2 = integer -> new Person[integer];
//构造器引用的格式
Function<Integer,Person[]> fu3 = Person[] :: new;

  • 25
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二狗mao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值