Lambda使用(三)->方法引用与构造器引用

Lambda的方法引用

若 Lambda 体中的功能,已经有相应的方法提供了实现,可以在Lambda体中引用该方法。(可以将方法引用理解为 Lambda 表达式的另外一种表现形式)。
下面以一个简单实例演示
由于Consumer函数式接口如下

@FunctionalInterface
public interface Consumer {
    /*传入一个类型,返回void*/
    void accept(T t);
}

我们要用该接口的Lambda表达式实现字符串的输出功能,如下:

    @Test
    public void test(){
        Consumer consumer = (s) -> {
            if (s != null) {
                System.out.println(s);
            }else{
                System.out.println("s 为空");
            }
        };

        consumer.accept("lzj");
        System.out.println("------------");
        consumer.accept(null);
    }
}

运行测试方法,输出:

lzj
------------
s 为空

此时,如果Lambda体中的内容已经被其它方法实现了,此时不必在Lambda体中再实现一遍了,直接调用相应的方法即可。例如有一个Info类中的show方法实现了相同的功能:

public class Info {
    /*传入一个类型,返回一个void*/
    public void show(T s){
        if (s != null) {
            System.out.println(s);
        }else{
            System.out.println("s 为空");
        }
    }
}

此时在用Consumer的函数接口Lambda表达式时,可以用下面的形式,实现了相同的功能。

    @Test
    public void test2(){
        Info info = new Info<>();
        Consumer consumer = info::show;
        consumer.accept("lzj");
        System.out.println("-----------");
        consumer.accept(null);
    }

在上面的示例中,Consumer接口中的accept方法的参数和返回值要和Info中的show方法中的参数和返回值一致方可用上面的形式。

Lambda的方法引用形式有以下三种形式

 1. 对象的引用 :: 实例方法名
 2. 类名 :: 静态方法名
 3. 类名 :: 实例方法名

一、对象的引用 :: 实例方法名
1、用Lambda表达式实现打印字符串

    @Test
    public void test1(){
        Consumer consumer = (x) -> System.out.println(x);
        consumer.accept("lzj");
    }

2、用Lambda的方法引用方式实现字符串打印

    @Test
    public void test1(){        
        PrintStream ps = System.out;
        /*Consumer接口中的accept方法的参数和返回值同println方法的参数和返回值相同*/
        Consumer consumer1 = ps::println;
        consumer1.accept("lzj");
    }

两种方式运行结果相同,都输出:lzj

二、类名 :: 静态方法名
例如我们要用Comparator接口的compare方法实现比较两个整数值的大小
1、用Lambda表达式表示如下

    @Test
    public void test3(){
        Comparator<Integer> comparator = 
                (x, y) -> {
                    Integer differ = x < y ? -1 : ((x == y) ? 0 : 1);
                    return differ;
                };
        Integer differ1 = comparator.compare(10, 5);
        System.out.println("differ1 : " + differ1);
    }

2、用Lambda的方法引用
由于Integer类中的compare静态方法已经实现了比较两个整数的大小,重要的是,Integer中的compare方法与Comparator接口中的compare方法的参数和返回值一致。

    @Test
    public void test3(){
        Comparator<Integer> comparator2 = Integer::compare;
        Integer differ2 = comparator2.compare(10, 5);
        System.out.println("differ2 : " + differ2);
    }

以上两种形式运行,输出结果相同:differ1 : 1

三、类名 :: 实例方法名
1、用Lambda表达式实现比较两个字符串的大小

    @Test
    public void test4(){
        BiPredicate<String, String> bp =
                (x, y) -> {
                    Boolean flag = x.equals(y);
                    return flag;
                };
        Boolean flag = bp.test("lzj", "lzj");
        System.out.println("flag : " + flag);
    }

2、用Lambda的方法引用
String 类中的equals方法已经实现了比较两个字符串大小,可以通过该方法实现Lambda的方法引用。前两种方式都是函数式接口的输入参数和实现Lambda体功能的方法的传入方法一致,如果不一致时,函数式接口中两个参数,其中一个通过方法调用另一参数时可以用下面形式

    @Test
    public void test4(){        
        BiPredicate<String, String> bp1 = String::equals;
        Boolean flag1 = bp1.test("lzj", "lzj");
        System.out.println("flag1 : " + flag1);
    }

BiPredicate接口中传入两个参数“lzj”和“lzj”,一个参数通过方法调用另一个,"lzj".equals("lzj") ,在用Lambda的方法引用时可以写成 String::equals的形式。

Lambda的构造器引用

public class User {

    private String name;
    private Integer age;

    public User() {
        super();
    }

    public User(String name) {
        super();
        this.name = name;
    }

    public User(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }

}

1、用Lambda表达式实现分别通过User的无参构造器和一个有参构造器获得User对象

    @Test
    public void test5(){
        Supplier supplier =
                () -> {return new User();}; //() -> new User();如果Lambda体中只有一条语句,可以省略return
        User user1 = supplier.get();    
        System.out.println("user1 : " + user1);

        System.out.println("-----------------------------------");

        Function function =
                (x) -> {
                    User user = new User(x);
                    return user;
                };
        User user = function.apply("lzj");
        System.out.println("user : " + user);

    }

2、Lambda的构造器引用分别实现通过User的无参构造器和一个有参构造器获得User对象

    @Test
    public void test6(){
        Supplier supplier = User::new;
        /*get方法无参,有返回值,所以调用的User的无参构造器,返回User对象*/
        User user1 = supplier.get();
        System.out.println("user1 : " + user1);

        System.out.println("-----------------------------------");

        Function function = User::new;
        /*apply方法有一个参数,有返回值,所以调用User的一个参数的构造器,并返回User对象*/
        User user = function.apply("lzj");
        System.out.println("user : " + user);
    }

两种方式输出结果相同:

user1 : User [name=null, age=null]
-----------------------------------
user : User [name=lzj, age=null]

Lambda的数组引用

    @Test
    public void test7(){
        Function function =
                (x) -> new String[x]; //省略retuen的写法
        String[] ss = function.apply(5);
        System.out.println("ss.length : " + ss.length);

        Function function1 = String[]::new;
        String[] sss = function1.apply(5);
        System.out.println("sss.length : " + sss.length);

    }

你可能感兴趣的:(java笔记)