1. 程式人生 > >Java8新特性之Lambda表示式學習二

Java8新特性之Lambda表示式學習二

大家好,又來到超超部落格大本營啦!歡迎大家......

上一章我們講解了Lambda表示式的基礎語法,引數列表、變數等知識點,接下來我們接續探究Lambda的表示式、以及其中的方法引用。

一、Lambda的表示式:

(1)如果表示式只有一行,那麼可以直接寫(不需要{});

(2)如果表示式有多行,就需要用{}變成程式碼塊,就應該要符合正常的Java語法;

(3)如果表示式是程式碼塊,並且方法需要返回值,那麼在程式碼塊中就必須要返回一個該型別的值;

(4)如果只有單行的情況,並且方法需要返回值,不能有return,因為此時是表示式,而不是程式碼塊,編譯器會自動幫我們推匯出return的返回值;

例1:依然是字串陣列排序

    public void test2(){
        String[] strs = new String[]{"Android","IOS","Java","OS"};
        /**
         * Lambda表示式若有多行,就需要用{}變成程式碼塊,就應該要符合正常的Java語法
         */
        Arrays.sort(strs,(final String s1,final String s2) ->{
            if(s1 != null && s2 != null) {
                return Integer.compare(s1.length(), s2.length());
            }
            return -1;
        });
        System.out.println(Arrays.toString(strs));

        //只有單行,並且方法需要返回值,不能有return,因為此時是表示式,而不是程式碼塊,編譯器會自                    
           動幫我們推匯出return的返回值;
         Arrays.sort(strs,(final String s1,final String s2) -> Integer.compare(s1.length(), s2.length()));
         
        System.out.println(Arrays.toString(strs));
    }

二、Lambda表示式中的方法引用:

(1) 類::靜態方法

例2:繼續改造整型陣列元素的排序

   public void testLambda() {
        Integer[] arr = new Integer[]{2, 5, 3, 8, 6, 10, 9};
        /**
         * 第一:Comparator介面中的compare()方法的兩個引數(x,y),原封不動的直接傳遞給了Integer.compare()方法;
         * 第二:可以直接將其Integer中的compare()方法看成是Comparator介面中的compare()方法的實現,引數型別、引數個數、方法返回值相同,方法名可以不相同哈;
         */
        Arrays.sort(arr,(x,y) -> Integer.compare(x, y));
        System.out.println(Arrays.toString(arr));

        /**
         * 借於上述,可以繼續改寫Lambda表示式;
         * 使用方法引用(類::靜態方法)
         */
        Arrays.sort(arr, Integer::compare);
        System.out.println(Arrays.toString(arr));
    }

(2) 物件::方法

例3:直接輸出陣列中的元素列表

   public void testLambda() {
        List<Integer> list = Arrays.asList(2, 5, 3, 8, 6, 10, 9);

        //原生的寫法
        list.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer x) {
                System.out.println(x);
            }
        });
        System.out.println(Arrays.toString(arr));

        /* Lambda表示式簡化操作
         * 第一:System.out是一個PrintStream物件,println()是該物件的一個方法;
         * 第二:println(Obejct x)這個方法本身需要傳入一個Object物件;
         * 第三:而列印x就是直接將x物件原封不動的交由System.out.println()這個方法,然後呼叫物件的toString()方法列印即可;
         * 第四:我們就可以理解為System.out物件的println()方法,在其呼叫了物件toString()方
         * 法,就是替代了Consumer介面中的accept()方法(需要滿足:方法引數型別個數相同,返回值相
         * 同,方法名可以不同);
         */
        list.forEach(System.out::println);

        System.out.println(Arrays.toString(arr));
    }

(3) 物件::靜態方法(自己舉例,不在贅述)

(4) 類::new      ==>不好理解,需要下來繼續揣摩 (本質上還是函式式介面,匿名內部類的改寫)

首先我們先定義一個函式式介面:

注意構造器引用對應的函式式接口裡面的方法格式一定是:返回一個物件

import java.util.List;

@FunctionalInterface
public interface IMyCreator<T extends List<?>> {

    T create();

}

其次,書寫我們的Lambda表示式:

public class TestLambda {
    
    //改裝Arrays中的asList()方法
    public <T> List<T> asList(IMyCreator<List<T>> creator, T... a) {
        List<T> list = creator.create();
        for (T t : a) {
            list.add(t);
        }
        return list;
    }

    @Test
    public void test() {

        //使用匿名內部類建立物件
        List<Integer> list1 = this.asList(new IMyCreator<List<Integer>>() {
            @Override
            public List<Integer> create() {
                return new ArrayList();
            }
        },2,3,4,5,6);

        /**
         * 第一:asList()方法第一個引數,一定是IMyCreator介面的例項;
         * 第二:建立IMyCreator介面例項,一定要重寫create()方法;
         * 第三:重寫create()方法,一定要返回一個泛型 T 的物件(T 和傳入型別等同);
         * 這些都是JVM幫助我們自動補全,可以改寫為下面Lambda表示式。
         */
        List<Integer> list2 = this.asList(() -> {
            return new ArrayList();
        }, 3, 4, 5, 6);

        //繼續改寫
        List<Integer> list3 = this.asList(() -> new ArrayList(),2,3,4,5,6);

        //最終改寫,使用構造方法引用,類::new
        List<Integer> list4 = this.asList(ArrayList::new, 2, 3, 4, 5, 6);
        list4.forEach(System.out::println);
    }

}

三、自己實現一個函式式介面,並將匿名內部類改寫為Lambda表示式

先建立一個介面,並用@FunctionInteface修飾

@FunctionalInterface
public interface IMyWork {

    public void doWork();

}

簡單實現: 

    @Test
    public void testLambda(){
        IMyWork work = () -> System.out.print("this is @FunctionInterface");
        work.doWork();
    }

注意要點:

第一:我們能寫Lambda表示式的地方?需滿足一個介面,且接口裡面只有一個抽象方法;

第二:在Java中,把只有一個抽象方法的介面稱為函式式介面,如果一個介面是函式式介面,我們可以在介面上新增@FunctionInterface,表明這是一個函式式介面;(1、自動檢查;2、文件) 

第三:無論是否標識@FunctionInterface,只要滿足函式式介面的介面,Java都會識別為函式式介面;

第四:簡化函式式介面的使用是Java中提供Lambda表示式唯一的作用;

第五:可以用介面直接來引用一個Lambda表示式;

第六:Lambda表示式中的異常處理:Lambda表示式中產生的異常,要麼在程式碼塊中直接處理,要麼在介面的方法宣告丟擲;

 

好啦,Lambda表示式基礎語法、簡單使用都講解完了,接下來就需要大家靈活應用於平常的Java程式碼中,使得自己的Java程式碼乾淨,整潔!有啥問題,請大家及時指出,很希望一起進步努力......

學習完超超的Lambda表示式,還不來看看Stream的基礎知識:Java8新特性之Stream詳解