Lambda表達(dá)式詳解

什么是Lambda表達(dá)式

Lambda表達(dá)式是Java 8的新特性掷漱,是函數(shù)式接口的實(shí)例。使用Lambda表達(dá)式可以寫(xiě)出更簡(jiǎn)潔、更靈活的代碼。

Lambda表達(dá)式語(yǔ)法

Lambda語(yǔ)法格式:

(parameters) -> expression
// 或
(parameters) -> { statements; }

->:叫做Lambda操作符箭頭操作符遍坟。

->左邊:Lambda形參列表(其實(shí)就是借口中的抽象方法的形參列表)

->右邊:Lambda體(其實(shí)就是重寫(xiě)的抽象方法的方法體)

Lambda表達(dá)式的使用

這里我們將Lambda表達(dá)式的使用細(xì)分為6中情況,下面結(jié)合例子進(jìn)行介紹:

  1. 情況一:無(wú)參晴股,無(wú)返回值

    public class LambdaTest {
        //語(yǔ)法格式一:無(wú)參愿伴,無(wú)返回值
        @Test
        public void test1() {
         //普通寫(xiě)法
            Runnable r1 = new Runnable() {
                @Override
                public void run() {
                    System.out.println("公眾號(hào):程序員汪汪------關(guān)注我");
                }
            };
            r1.run();
            System.out.println("**************************");
         //Lambda表達(dá)式的寫(xiě)法
            Runnable r2 = () -> System.out.println("公眾號(hào):程序員汪汪------關(guān)注我");
            r2.run();
    
        }
    }
    
  2. 情況二:Lambda表達(dá)式需要一個(gè)參數(shù),但是沒(méi)有返回值队魏。

    //語(yǔ)法格式二:Lambda需要一個(gè)參數(shù)公般,但是沒(méi)有返回值
        @Test
        public void test2() {
            //普通寫(xiě)法
            Consumer<String> con = new Consumer<String>() {
                @Override
                public void accept(String s) {
                    System.out.println(s);
                }
            };
            con.accept("公眾號(hào):程序員汪汪------關(guān)注我");
    
            System.out.println("**************************");
         //Lambda表達(dá)式的寫(xiě)法
            Consumer<String> con1 = (String s) -> {System.out.println(s);};
            con1.accept("公眾號(hào):程序員汪汪------關(guān)注我");
    
        }
    
  3. 情況三:數(shù)據(jù)類(lèi)型可以省略,因?yàn)榭捎删幾g器推斷得出胡桨,稱(chēng)為類(lèi)型推斷

    //語(yǔ)法格式三:數(shù)據(jù)類(lèi)型可以省略,因?yàn)榭捎删幾g器推斷得出瞬雹,稱(chēng)為“類(lèi)型推斷”
        @Test
        public void test3() {
            Consumer<String> con1 = (String s) -> {
                System.out.println(s);
            };
            con.accept("公眾號(hào):程序員汪汪------關(guān)注我");
    
            System.out.println("**************************");
    
            //Lambda表達(dá)式的寫(xiě)法
            Consumer<String> con1 = (String s) -> {System.out.println(s);};
            con1.accept("公眾號(hào):程序員汪汪------關(guān)注我");
        }
    
  4. 情況四:Lambda表達(dá)式若只需要一個(gè)參數(shù)時(shí)昧谊,參數(shù)的小括號(hào)可以省略

    //語(yǔ)法格式四:Lambda 若只需要一個(gè)參數(shù)時(shí),參數(shù)的小括號(hào)可以省略
        @Test
        public void test4() {
            Consumer<String> con1 = (s) -> {
                System.out.println(s);
            };
            con1.accept("hhhhh");
    
            System.out.println("***************");
    
            Consumer<String> con2 = s -> {
                System.out.println(s);
            };
            con2.accept("hhhhhhhhhhhh");
    
        }
    

    注意:無(wú)參數(shù)時(shí)酗捌,小括號(hào)是一定不能省略的呢诬。

  5. 情況五:Lambda表達(dá)式需要兩個(gè)或兩個(gè)以上的參數(shù)涌哲,有多條執(zhí)行語(yǔ)句,并且可以有返回值

    //語(yǔ)法格式五:Lambda表達(dá)式需要兩個(gè)或兩個(gè)以上的參數(shù)尚镰,有多條執(zhí)行語(yǔ)句阀圾,并且可以有返回值
        @Test
        public void test5() {
            Comparator<Integer> com1 = new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    System.out.println(o1);
                    System.out.println(o2);
                    return o1.compareTo(o2);
                }
            };
            System.out.println(com1.compare(12, 21));
            System.out.println("***********************");
    
            Comparator<Integer> com2 = (o1, o2) -> {
                System.out.println(o1);
                System.out.println(o2);
                return o1.compareTo(o2);
            };
            System.out.println(com2.compare(12, 6));
        }
    
  6. 情況六:當(dāng)Lambda體只有一條語(yǔ)句時(shí),return 與大括號(hào)若有狗唉,都可以省略

    //語(yǔ)法格式六:當(dāng) Lambda 體只有一條語(yǔ)句時(shí)初烘,return 與大括號(hào)若有,都可以省略
        @Test
        public void test6() {
            Comparator<Integer> com1 = (o1, o2) -> {
                return o1.compareTo(o2);
            };
            System.out.println(com1.compare(12, 6));
    
            System.out.println("****************");
    
            Comparator<Integer> com2 = (o1, o2) -> o1.compareTo(o2);
    
            System.out.println(com2.compare(12, 26));
    
        }
    

總結(jié)

->左邊:Lambda表達(dá)式的形參列表的參數(shù)類(lèi)型可以省略(類(lèi)型推斷)分俯;如果Lambda形參列表只有一個(gè)參數(shù)肾筐,其一對(duì)()可以省略,沒(méi)有參數(shù)和有多個(gè)參數(shù)的情況下()不能省略缸剪。

->右邊:Lambda體應(yīng)該使用一對(duì){}包裹吗铐;如果Lambda體只有一條執(zhí)行語(yǔ)句(可能是return語(yǔ)句),其一對(duì){}可以省略杏节,如果是return語(yǔ)句唬渗,想要省略一對(duì){},那么return關(guān)鍵字也必須省略奋渔;有多條語(yǔ)句時(shí)谣妻,不能省略。

Lambda表達(dá)式的本質(zhì):作為函數(shù)式接口的實(shí)例卒稳。函數(shù)式接口就是只聲明了一個(gè)抽象方法的接口蹋半。

函數(shù)式接口

函數(shù)式接口就是只聲明了一個(gè)抽象方法的接口。

在Java 8中充坑,java.util.function包下定義了豐富的函數(shù)式接口减江,這些接口上都使用了@FunctionalInterface注解,這樣可以檢查它是否是一個(gè)函數(shù)式接口捻爷。我們也可以使用該注解定義自己的函數(shù)式接口辈灼。

想要使用Lambda表達(dá)式,那么就一定需要函數(shù)式接口也榄,Lambda就是函數(shù)式接口的實(shí)例巡莹。

java內(nèi)置四大核心函數(shù)式接口

函數(shù)式接口 參數(shù)類(lèi)型 返回類(lèi)型 用途
Consumer<T><br />消費(fèi)型接口 T void 對(duì)類(lèi)型為T(mén)的對(duì)象應(yīng)用操作。包含方法:void accept(T t)
Supplier<T><br />供給型接口 無(wú) T 返回類(lèi)型為T(mén)的對(duì)象甜紫,包含方法:T get()
Function<T, R><br />函數(shù)型接口 T R 對(duì)類(lèi)型為T(mén)的對(duì)象應(yīng)用操作降宅,并返回結(jié)果。結(jié)果類(lèi)型是R類(lèi)型的對(duì)象囚霸。方法包含:R apply(T t)
Predicate<T><br />斷定型接口 T boolean 確定類(lèi)型為T(mén)的對(duì)象是否滿(mǎn)足某約束腰根,并返回boolean值。包含方法:boolean test(T t)

其他接口

函數(shù)式接口 參數(shù)類(lèi)型 返回類(lèi)型 用途
BiFunction<T, U, R> T, U R 對(duì)類(lèi)型為T(mén), U參數(shù)應(yīng)用操作拓型,返回R類(lèi)型的結(jié)果额嘿。包含方法:R apply(T t, U u)
UnaryOperator<T><br />(Function子接口) T T 對(duì)類(lèi)型為T(mén)的對(duì)象進(jìn)行一元運(yùn)算瘸恼,并返回T類(lèi)型的結(jié)果。包含方法:T apply(T t)
BinaryOperator<T><br />(BiFunction子接口) T, T T 對(duì)類(lèi)型為T(mén)的對(duì)象進(jìn)行二元運(yùn)算册养,并返回T類(lèi)型的結(jié)果东帅。包含方法:T apply(T t1, T t2)
BiConsumer<T, U> T, U void 對(duì)類(lèi)型為T(mén), U參數(shù)應(yīng)用操作。包含方法:void accept(T t, U u)
BiPredicate<T, U> T, U boolean 包含方法:boolean test(T t, U u)
ToIntFunction<T><br />ToLongFunction<T><br />ToDoubleFunction<T> T int<br />long<br />double 分別計(jì)算int球拦、long靠闭、double值得函數(shù)
IntFunction<R><br />LongFunction<R><br />DoubleFunction<R> int<br />long<br />double R 參數(shù)分別為int、long刘莹、double類(lèi)型的函數(shù)

Java提供的函數(shù)式接口還有很多阎毅,上表只列舉了一部分函數(shù)式接口,在以后的開(kāi)發(fā)中可能會(huì)遇到点弯。凡是開(kāi)發(fā)中遇到了函數(shù)式接口扇调,都可以運(yùn)用Lambda表達(dá)式。

函數(shù)式接口的基本命名準(zhǔn)則

Java提供的函數(shù)式接口遵循以下基本命名準(zhǔn)則:

  1. 如果只處理對(duì)象而非基本類(lèi)型抢肛,名稱(chēng)則為 Function狼钮,ConsumerPredicate 等捡絮。參數(shù)類(lèi)型通過(guò)泛型添加熬芜。
  2. 如果接收的參數(shù)是基本類(lèi)型,則由名稱(chēng)的第一部分表示福稳,如 LongConsumer涎拉,DoubleFunctionIntPredicate 等的圆,但返回基本類(lèi)型的 Supplier 接口例外鼓拧。
  3. 如果返回值為基本類(lèi)型,則用 To 表示越妈,如 ToLongFunction <T>IntToLongFunction季俩。
  4. 如果返回值類(lèi)型與參數(shù)類(lèi)型相同,則是一個(gè) Operator :?jiǎn)蝹€(gè)參數(shù)使用 UnaryOperator梅掠,兩個(gè)參數(shù)使用 BinaryOperator酌住。
  5. 如果接收參數(shù)并返回一個(gè)布爾值,則是一個(gè) 斷言 (Predicate)阎抒。
  6. 如果接收的兩個(gè)參數(shù)類(lèi)型不同酪我,則名稱(chēng)中有一個(gè) Bi

這里使用java內(nèi)置的四大核心函數(shù)式接口舉兩個(gè)例子:

public class LambdaTest2 {
    //消費(fèi)型接口Consumer
    public void happyTime(double money, Consumer<Double> consumer) {
        consumer.accept(money);
    }

    @Test
    public void test() {
        happyTime(500, new Consumer<Double>() {
            @Override
            public void accept(Double aDouble) {
                System.out.println("學(xué)習(xí)好累啊挠蛉,出去嗨一下祭示,花了" + aDouble + "元");
            }
        });
        System.out.println("******************************");

        happyTime(400, money -> {
            System.out.println("學(xué)習(xí)好累啊,出去嗨一下谴古,花了" + money + "元");
        });
    }

    //根據(jù)給定的規(guī)則质涛,過(guò)濾集合中的字符串。此規(guī)則由Predicate的方法決定
    public List<String> filterString(List<String> list, Predicate<String> predicate) {
        ArrayList<String> filterList = new ArrayList<>();
        for (String s : list) {
            if (predicate.test(s)) {
                filterList.add(s);
            }
        }

        return filterList;
    }

    //斷定型接口 Predicate
    @Test
    public void test2(){
        List<String> list = Arrays.asList("北京", "南京", "天津", "東京", "西京", "普京");
        //普通寫(xiě)法
        List<String> filterList = filterString(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("京");
            }
        });
        System.out.println(filterList);

        System.out.println("******************************");
        //Lambda表達(dá)式寫(xiě)法
        List<String> filterList2 = filterString(list, s -> s.contains("京"));
        System.out.println(filterList2);
    }

}
/**
test1 運(yùn)行結(jié)果:
    學(xué)習(xí)好累啊掰担,出去嗨一下汇陆,花了500.0元
    ******************************
    學(xué)習(xí)好累啊,出去嗨一下带饱,花了400.0元
test2 運(yùn)行結(jié)果:
    [北京, 南京, 東京, 西京, 普京]
    ******************************
    [北京, 南京, 東京, 西京, 普京]

*/

方法引用

方法引用本質(zhì)上就是Lambda表達(dá)式毡代,而Lambda是函數(shù)式接口的實(shí)例,所以方法引用也是函數(shù)式接口的實(shí)例

使用情境:當(dāng)要傳遞給Lambda體的操作勺疼,已經(jīng)有實(shí)現(xiàn)的方法了教寂,可以使用方法引用。

方法引用的格式:

類(lèi)(或?qū)ο螅?:: 方法名

具體可以分為如下的三種情況:

  1. 對(duì)象 :: 非靜態(tài)方法
  2. 類(lèi) :: 靜態(tài)方法
  3. 類(lèi) :: 非靜態(tài)方法

案例

Employee工具類(lèi):

public class Employee {

    private int id;
    private String name;
    private int age;
    private double salary;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Employee() {

    }

    public Employee(int id) {

        this.id = id;
    }

    public Employee(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Employee(int id, String name, int age, double salary) {

        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        Employee employee = (Employee) o;

        if (id != employee.id)
            return false;
        if (age != employee.age)
            return false;
        if (Double.compare(employee.salary, salary) != 0)
            return false;
        return name != null ? name.equals(employee.name) : employee.name == null;
    }

    @Override
    public int hashCode() {
        int result;
        long temp;
        result = id;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + age;
        temp = Double.doubleToLongBits(salary);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        return result;
    }
}

測(cè)試類(lèi):

public class MethodRefTest {

    // 情況一:對(duì)象 :: 實(shí)例方法
    //Consumer中的void accept(T t)
    //PrintStream中的void println(T t)
    @Test
    public void test1() {

        //普通寫(xiě)法
        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        con.accept("hello!");
        System.out.println("*****************************");
        //Lambda表達(dá)式寫(xiě)法
        Consumer<String> con1 = str -> System.out.println(str);
        con1.accept("北京");

        System.out.println("*****************************");
        //方法引用的寫(xiě)法
        PrintStream ps = System.out;
        Consumer<String> con2 = ps::println;
        con2.accept("天安門(mén)");
        
        /**
        test1 運(yùn)行結(jié)果:
            hello!
            *****************************
            北京
            *****************************
            天安門(mén)
        */

    }

    //Supplier中的T get()
    //Employee中的String getName()
    @Test
    public void test2() {
        //普通寫(xiě)法
        Employee emp = new Employee(1001, "Tom", 20, 5000);
        Supplier<String> sup = new Supplier<String>() {
            @Override
            public String get() {
                return emp.getName();
            }
        };
        System.out.println(sup.get());
        System.out.println("***************************************");
        //Lambda表達(dá)式寫(xiě)法执庐,emp對(duì)象不變
        Supplier<String> sup1 = () -> emp.getName();
        System.out.println(sup1.get());
        System.out.println("***************************************");
        //方法引用的寫(xiě)法
        Supplier<String> sup2 = emp::getName;
        System.out.println(sup2.get());
        
        /**
        test2 運(yùn)行結(jié)果:
            Tom
            ***************************************
            Tom
            ***************************************
            Tom
        */

    }

    // 情況二:類(lèi) :: 靜態(tài)方法
    //Comparator中的int compare(T t1,T t2)
    //Integer中的int compare(T t1,T t2)
    @Test
    public void test3() {
        //普通寫(xiě)法
        Comparator<Integer> com = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1, o2);
            }
        };
        System.out.println(com.compare(12, 20));
        System.out.println("***************************************");
        //Lambda 表達(dá)式的寫(xiě)法
        Comparator<Integer> com1 = (o1, o2) -> Integer.compare(o1, o2);
        System.out.println(com1.compare(12, 20));
        System.out.println("***************************************");
        //方法引用
        Comparator<Integer> com2 = Integer::compare;
        System.out.println(com2.compare(12, 20));
        /**
        test3 運(yùn)行結(jié)果:
            -1
            ***************************************
            -1
            ***************************************
            -1
        */
    }

    //Function中的R apply(T t)
    //Math中的Long round(Double d)
    @Test
    public void test4() {
        //普通寫(xiě)法
        Function<Double, Long> fun = new Function<Double, Long>() {
            @Override
            public Long apply(Double aDouble) {
                return Math.round(aDouble);
            }
        };
        System.out.println(fun.apply(12.3));
        System.out.println("***************************************");
        //Lambda表達(dá)式寫(xiě)法
        Function<Double, Long> fun1 = (aDouble) -> Math.round(aDouble);
        System.out.println(fun1.apply(12.6));
        System.out.println("***************************************");
        //方法引用的寫(xiě)法
        Function<Double, Long> fun2 = Math::round;
        System.out.println(fun2.apply(12.5));
        /**
        test4 運(yùn)行結(jié)果:
            12
            ***************************************
            13
            ***************************************
            13
        */

    }

    // 情況三:類(lèi) :: 實(shí)例方法
    // Comparator中的int compare(T t1,T t2)
    // String中的int t1.compareTo(t2)
    @Test
    public void test5() {
        //普通方法
        Comparator<String> com = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        };
        System.out.println(com.compare("abc", "abe"));
        System.out.println("***************************************");
        //Lambda 表達(dá)式的方式
        Comparator<String> com1 = (o1, o2) -> o1.compareTo(o2);
        System.out.println(com1.compare("abc", "abe"));
        System.out.println("***************************************");
        //方法引用的方式
        Comparator<String> com2 = String::compareTo;
        System.out.println(com2.compare("abc", "abe"));
        /**
        test5 運(yùn)行結(jié)果:
            -2
            ***************************************
            -2
            ***************************************
            -2
        */

    }

    //BiPredicate中的boolean test(T t1, T t2);
    //String中的boolean t1.equals(t2)
    @Test
    public void test6() {
        //普通寫(xiě)法
        BiPredicate<String, String> bip = new BiPredicate<String, String>() {
            @Override
            public boolean test(String s, String s2) {
                return s.equals(s2);
            }
        };
        System.out.println(bip.test("abc", "abd"));
        System.out.println("***************************************");
        //Lambda表達(dá)式寫(xiě)法
        BiPredicate<String, String> bip1 = (s1, s2) -> s1.equals(s2);
        System.out.println(bip1.test("abc", "abc"));
        System.out.println("***************************************");
        //方法引用
        BiPredicate<String, String> bip2 = String::equals;
        System.out.println(bip2.test("abc", "abc"));
        
        /**
        test6 運(yùn)行結(jié)果:
            false
            ***************************************
            true
            ***************************************
            true
        */

    }

    // Function中的R apply(T t)
    // Employee中的String getName();
    @Test
    public void test7() {
        //普通寫(xiě)法
        Employee emp = new Employee(1001, "Tom", 20, 5000);
        Function<Employee, String> func = new Function<Employee, String>() {
            @Override
            public String apply(Employee employee) {
                return employee.getName();
            }
        };
        System.out.println(func.apply(emp));
        System.out.println("***************************************");
        //Lambda 表達(dá)式的寫(xiě)法 emp不變
        Function<Employee, String> func1 = employee -> employee.getName();
        System.out.println(func1.apply(emp));
        System.out.println("***************************************");
        //方法引用寫(xiě)法
        Function<Employee, String> func2 = Employee::getName;
        System.out.println(func2.apply(emp));
        /**
        test7 運(yùn)行結(jié)果:
            Tom
            ***************************************
            Tom
            ***************************************
            Tom
        */
    }
    

}

方法引用使用的要求:要求接口中的抽象方法的形參列表和返回值類(lèi)型與方法引用的方法的形參列表和返回值類(lèi)型相同酪耕,如果是成員方法(非靜態(tài)方法),會(huì)在方法的參數(shù)列表的第一個(gè)位置增加this的類(lèi)型轨淌。

分析

首先我們來(lái)分析一下test1的例子ps::println迂烁,在本例中,實(shí)際上調(diào)用的是void println(String str)递鹉,它是非靜態(tài)方法盟步,也就是成員方法,按照上述的要求躏结,需要在參數(shù)列表的第一個(gè)位置補(bǔ)上this也就是PrintStream却盘,參數(shù)列表就變成了這樣void println(PrintStream ps String str),但是因?yàn)?code>::前是一個(gè)PrintStream實(shí)例ps媳拴,因此黄橘,方法引用的第一個(gè)參數(shù)this被綁定給了ps,所以最終的參數(shù)列表又變回了void println(String str)禀挫,所以就符合了要求中所說(shuō)的參數(shù)列表和返回值類(lèi)型都與方法引用的方法的形參列表和返回值類(lèi)型相同的要求旬陡,那么就和Consumer<T>接口的抽象方法void accept(T t)的返回值和參數(shù)列表一致了,所以就可以使用方法引用语婴。

再來(lái)看test3的例子描孟,test3是情況2的例子,調(diào)用的是靜態(tài)方法砰左,靜態(tài)方法沒(méi)有this匿醒,所以只要滿(mǎn)足參數(shù)列表和返回值相同的條件就可以使用方法引用。

最后看test5的例子String::compareTo缠导,在這個(gè)例子中廉羔,int compareTo(String str)是一個(gè)成員方法(非靜態(tài)方法),按照上述的方法引用使用的要求僻造,需要在參數(shù)列表的第一個(gè)位置上補(bǔ)上this(在這里憋他,this的類(lèi)型就是String)孩饼,為什么是String?因?yàn)?code>compareTo是String類(lèi)的成員方法竹挡,this當(dāng)然就是指的是String镀娶。添加this后,新的參數(shù)列表就變成了int compareTo(String s, String str)揪罕,此時(shí)就符合Comparator接口中的int compare(T t1,T t2)的要求梯码,所以方法引用就能夠使用了。

總結(jié)

  1. 成員方法(非靜態(tài)方法)的參數(shù)列表好啰,前面會(huì)追加this的類(lèi)型轩娶。
  2. 靜態(tài)方法因?yàn)闆](méi)有this,所以參數(shù)列表不會(huì)追加任何東西
  3. 當(dāng)::前是一個(gè)實(shí)例時(shí)框往,本應(yīng)追加到參數(shù)列表中的this會(huì)綁定給這個(gè)實(shí)例鳄抒。

構(gòu)造器引用與數(shù)組引用

構(gòu)造器引用:構(gòu)造器引用和方法引用類(lèi)似,函數(shù)式接口的抽象方法的形參列表和構(gòu)造器的形參列表一致搅窿,抽象方法的返回值類(lèi)型即為構(gòu)造器所屬的類(lèi)的類(lèi)型嘁酿。

數(shù)組引用:把數(shù)組看成是一個(gè)特殊的類(lèi),則寫(xiě)法就與構(gòu)造器引用一致了男应。

案例:

案例中仍需使用上面的Employee工具類(lèi)闹司。

public class ConstructorRefTest {
    //構(gòu)造器引用
    //Supplier中的T get()
    @Test
    public void test1(){
        //普通寫(xiě)法
        Supplier<Employee> sup = new Supplier<Employee>() {
            @Override
            public Employee get() {
                return new Employee();
            }
        };
        System.out.println(sup.get());
        System.out.println("***************************************");
        //Lambda 表達(dá)式寫(xiě)法
        Supplier<Employee> sup1 = () -> new Employee();
        System.out.println(sup1.get());
        System.out.println("***************************************");
        //構(gòu)造器引用寫(xiě)法
        Supplier<Employee> sup2 = Employee::new;
        System.out.println(sup2.get());
        
        /**
        運(yùn)行結(jié)果:
            Employee{id=0, name='null', age=0, salary=0.0}
            ***************************************
            Employee{id=0, name='null', age=0, salary=0.0}
            ***************************************
            Employee{id=0, name='null', age=0, salary=0.0}
        */
    }

    //Function中的R apply(T t)
    @Test
    public void test2(){
        //普通寫(xiě)法
        Function<Integer, Employee> func = new Function<Integer, Employee>() {
            @Override
            public Employee apply(Integer id) {
                return new Employee(id);
            }
        };
        System.out.println(func.apply(1001));
        System.out.println("***************************************");
        // Lambda
        Function<Integer, Employee> func1 = id -> new Employee(id);
        System.out.println(func1.apply(1002));
        System.out.println("***************************************");
        //構(gòu)造器引用
        Function<Integer, Employee> func2 = Employee::new;
        System.out.println(func2.apply(1003));
        
        /**
        運(yùn)行結(jié)果:
            Employee{id=1001, name='null', age=0, salary=0.0}
            ***************************************
            Employee{id=1002, name='null', age=0, salary=0.0}
            ***************************************
            Employee{id=1003, name='null', age=0, salary=0.0}
        */

    }

    //BiFunction中的R apply(T t,U u)
    @Test
    public void test3(){
        //普通寫(xiě)法
        BiFunction<Integer, String, Employee> func = new BiFunction<Integer, String, Employee>() {
            @Override
            public Employee apply(Integer id, String name) {
                return new Employee(id, name);
            }
        };
        System.out.println(func.apply(1001, "Tom"));
        System.out.println("***************************************");
        //Lambda
        BiFunction<Integer, String, Employee> func1 = (id, name) -> new Employee(id, name);
        System.out.println(func1.apply(1002, "Jerry"));
        System.out.println("***************************************");
        //構(gòu)造器引用
        BiFunction<Integer, String, Employee> func2 = Employee::new;
        System.out.println(func2.apply(1003, "Jack"));
        
        /**
        運(yùn)行結(jié)果:
            Employee{id=1001, name='Tom', age=0, salary=0.0}
            ***************************************
            Employee{id=1002, name='Jerry', age=0, salary=0.0}
            ***************************************
            Employee{id=1003, name='Jack', age=0, salary=0.0}
        */

    }

    //數(shù)組引用
    //Function中的R apply(T t)
    @Test
    public void test4(){
        //普通寫(xiě)法  Integer代表數(shù)組長(zhǎng)度
        Function<Integer, String[]> func1 = new Function<Integer, String[]>() {
            @Override
            public String[] apply(Integer length) {
                return new String[length];
            }
        };
        String[] arr1 = func1.apply(5);
        System.out.println(Arrays.toString(arr1));
        System.out.println("***************************************");
        //Lambda
        Function<Integer, String[]> func2 = length -> new String[length];
        String[] arr2 = func2.apply(8);
        System.out.println(Arrays.toString(arr2));
        System.out.println("***************************************");
        //數(shù)組引用
        Function<Integer, String[]> func3 = String[]::new;
        String[] arr3 = func3.apply(10);
        System.out.println(Arrays.toString(arr3));
        
        /**
        運(yùn)行結(jié)果:
            [null, null, null, null, null]
            ***************************************
            [null, null, null, null, null, null, null, null]
            ***************************************
            [null, null, null, null, null, null, null, null, null, null]
        */

    }
    
}

結(jié)語(yǔ):

Lambda表達(dá)式,還是需要多練多寫(xiě)沐飘,如果實(shí)在不會(huì)寫(xiě)游桩,可以使用IDEA的提示功能,在可以使用Lambda表達(dá)式的地方耐朴,可以通過(guò)提示借卧,自動(dòng)轉(zhuǎn)換成Lambda表達(dá)式。建議還是自己多寫(xiě)多練筛峭。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铐刘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子影晓,更是在濱河造成了極大的恐慌镰吵,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挂签,死亡現(xiàn)場(chǎng)離奇詭異疤祭,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)饵婆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)勺馆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事草穆」嘣郑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵续挟,是天一觀的道長(zhǎng)紧卒。 經(jīng)常有香客問(wèn)我侥衬,道長(zhǎng)诗祸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任轴总,我火速辦了婚禮直颅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怀樟。我一直安慰自己功偿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布往堡。 她就那樣靜靜地躺著械荷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪虑灰。 梳的紋絲不亂的頭發(fā)上吨瞎,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音穆咐,去河邊找鬼颤诀。 笑死,一個(gè)胖子當(dāng)著我的面吹牛对湃,可吹牛的內(nèi)容都是我干的崖叫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拍柒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼心傀!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起拆讯,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤脂男,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后往果,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體疆液,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年陕贮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了堕油。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖掉缺,靈堂內(nèi)的尸體忽然破棺而出卜录,到底是詐尸還是另有隱情,我是刑警寧澤眶明,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布艰毒,位于F島的核電站,受9級(jí)特大地震影響搜囱,放射性物質(zhì)發(fā)生泄漏丑瞧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一蜀肘、第九天 我趴在偏房一處隱蔽的房頂上張望绊汹。 院中可真熱鬧,春花似錦扮宠、人聲如沸西乖。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)获雕。三九已至,卻和暖如春收捣,著一層夾襖步出監(jiān)牢的瞬間届案,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工坏晦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萝玷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓昆婿,卻偏偏與公主長(zhǎng)得像球碉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仓蛆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容