天天看點

我愛Java系列---【lambda表達式】

一.lambda表達式(必須掌握)

    1.函數式程式設計思想概念

          函數式思想則盡量忽略面向對象的複雜文法——強調做什麼,而不是以什麼形式做

     2.lambda表達式寫法技巧:

         隻需要按照匿名内部類的形式寫出代碼,然後保留抽象方法的()和{},在()和{}之間添加一個->

     3.lambda表達式組成   

        (1)一些參數

         (2)一個箭頭

         (3)一段代碼

    4.lambda表達式格式:

         (參數清單...)->{代碼}

    5.lambda表達式格式解釋:

         (1)(參數清單...): 和以前定義方法的參數清單(寫在()中)是一緻的

             沒有參數()留白,有多個參數,用逗号隔開

         (2)->: 代表指向的動作,本質方法參數的傳遞

         (3){}: 和以前定義方法的{}中是一樣的,代表的是方法體的内容

     6.Lambda表達式的省略格式

         (1)資料類型可以省略: (Person p1,Person p2): 省略格式(p1,p2)

         (2)()中隻有一個參數,()可以省略: (Perons p): 省略格式(p)   最簡化的省略格式: p

         (3)->: 永遠不能省略

         (4){}中如果隻有一條語句:

             那麼{},return,分号 都可以省略

             但是要麼全部省略,要麼全部保留

     7.lambda表達式的前提

         (1)必須要有接口(函數式接口)

             要求接口中隻能有一個(必須要被覆寫重寫的)抽象方法,可以有預設方法,可以有靜态方法

         (2)必須要有接口作為方法的參數

             @Override:  檢測是否是對父類方法的覆寫重寫

             @FunctionalInterface: 檢測是否是函數式接口

二.常用的函數是接口

   1.消費型接口

         java.util.function.Consumer<T>: 消費型接口

             抽象方法:                                                                        必須掌握

                 public abstract void accept(T t): 消費一個指定泛型T類型的資料

                 注意:

                     什麼叫做消費呢?

                因為accept方法是抽象的,隻要做覆寫重寫{}後,就叫消費了,至于{}中寫了哪些代碼,我不管

  2.判斷型接口   

        java.util.function.Predicate<T>: 判斷型接口

             抽象方法:     必須掌握

                 public abstract boolean test(T t): 根據T類型的參數t,傳回一個boolean類型的結果

三.Stream流

    1.擷取Stream流對象的方法(兩種)

        (1)Collection<T>集合

             預設方法:必須由Collection接口的實作類(ArrayList/LinkedList/HashSet/LinkedHashSet)對象調用

            Stream<T> stream()  :擷取Collection集合對象的Stream流對象

         代碼示範:

                      //擷取List集合的Stream對象

              List<String> list = new ArrayList<>();                                    

                 Stream<String> s1 = list.stream();

                 System.out.println(s1);

                 //擷取Set集合的Stream對象

                 Set<Integer> set = new HashSet<>();

                 Stream<Integer> s2 = set.stream();

                 System.out.println(s2);

                 Map<String,String> map = new HashMap<>();

                //Map鍵的Set集合

                Set<String> set2 = map.keySet();

                Stream<String> s3 = set2.stream();

                System.out.println(s3);

                //Map值的Collection集合

                Collection<String> coll = map.values();

                Stream<String> s4 = coll.stream();

                System.out.println(s4);

               //Map鍵值對的Set集合

               Set<Map.Entry<String, String>> set3 = map.entrySet();

                Stream<Map.Entry<String, String>> s5 = set3.stream();

               System.out.println(s5);

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

               String[] arr = {"Hello","World","java"};

                Stream<String> s6 = Stream.of(arr);

               System.out.println(s6);

               Stream<String> s7 = Stream.of("Hello", "World", "java");

               System.out.println(s7);

}

}

         (2)Stream接口的靜态方法

            靜态方法

             java.util.stream.Stream<T> 接口:

            public static <T> Stream<T> of(T ... t): 把方法的可變參數指定的具體資料,

              轉換成Stream流對象

               參數:

                     T ... t: 可變參數 可以傳遞數組,參數清單,也可以不傳遞

Stream<String> s = Stream.of("大娃", "二娃", "娃"}      

     2.Stream流中的forEach方法

         void forEach(Consumer<T> action):  終結方法,調用此方法後,Stream流對象将不可以繼續使用

            該方法接收一個Consumer接口函數,會将每一個流元素交給該函數進行處理,不保證順序

        Consumer接口:

             抽象方法:

                 void accept(T t)

                 s->sout(s);System.out::println

     3.Stream流中的count方法

         long count() : 終結方法,調用此方法後,Stream流對象将不可以繼續使用

        傳回Stream流對象中的元素的個數,但是傳回值類型是long

    4.Stream流中的filter方法

         Stream<T> filter(Predicate<T> predicate) :

             按照方法參數predicate對Stream流對象中的元素進行過濾,并傳回新的Stream流對象

        Predicate<T>接口:

             抽象方法:

                 boolean test(T t)

     5.Stream流中的limit方法和skip方法

         Stream<T> limit(long n): 擷取流對象中的前n個元素,傳回新的Stream流對象

         Stream<T> skip(long n):  跳過流對象中的前n個元素,傳回新的Stream流對象           

     6.Stream流中的靜态concat方法

        static <T> Stream<T> concat(Stream<T> a, Stream<T> b):

             把兩個流對象a和b合并成一個流對象,并傳回

四、綜合案例

/*

Stream綜合案例

1. 第一個隊伍隻要名字為3個字的成員姓名;

2. 第一個隊伍篩選之後隻要前3個人;

3. 第二個隊伍隻要姓張的成員姓名;

4. 第二個隊伍篩選之後不要前2個人;

5. 将兩個隊伍合并為一個隊伍;

6. 列印整個隊伍的姓名資訊。

按照Stream流+匿名内部類的形式

*/

public class Demo02ListEach {

public static void main(String[] args) {

List<String> o = new ArrayList<>();

o.add("迪麗熱巴");

o.add("宋遠橋");

o.add("蘇星河");

o.add("老子");

o.add("莊子");

o.add("孫子");

o.add("洪七公");

//擷取第一個隊伍的流對象

Stream<String> os1 = o.stream();

//1. 第一個隊伍隻要名字為3個字的成員姓名;

Stream<String> os2 = os1.filter(new Predicate<String>() {

@Override

public boolean test(String s) {

return s.length() == 3;

}

});

//2. 第一個隊伍篩選之後隻要前3個人;

Stream<String> os3 = os2.limit(3);

List<String> t = new ArrayList<>();

t.add("古力娜紮");

t.add("張無忌");

t.add("張三豐");

t.add("趙麗穎");

t.add("張二狗");

t.add("張天愛");

t.add("張三");

//擷取第二個隊伍的流對象

Stream<String> ts1 = t.stream();

//3. 第二個隊伍隻要姓張的成員姓名;

Stream<String> ts2 = ts1.filter(new Predicate<String>() {

@Override

public boolean test(String s) {

return s.startsWith("張");

}

});

//4. 第二個隊伍篩選之後不要前2個人;

Stream<String> ts3 = ts2.skip(2);

//5. 将兩個隊伍合并為一個隊伍;

Stream<String> ots = Stream.concat(os3, ts3);

//6. 列印整個隊伍的姓名資訊

ots.forEach(new Consumer<String>() {

@Override

public void accept(String s) {

System.out.println(s);

}

});

}

}

/*
    Stream綜合案例
        1. 第一個隊伍隻要名字為3個字的成員姓名;
        2. 第一個隊伍篩選之後隻要前3個人;
        3. 第二個隊伍隻要姓張的成員姓名;
        4. 第二個隊伍篩選之後不要前2個人;
        5. 将兩個隊伍合并為一個隊伍;
        6. 列印整個隊伍的姓名資訊。

按照Stream流+lambda标準格式的形式(分4步完成)
 */public class Demo04ListEach {
    public static void main(String[] args) {
        List<String> o = new ArrayList<>();
        o.add("迪麗熱巴");
        o.add("宋遠橋");
        o.add("蘇星河");
        o.add("老子");
        o.add("莊子");
        o.add("孫子");
        o.add("洪七公");

        //擷取第一個隊伍的流對象

        //1. 第一個隊伍隻要名字為3個字的成員姓名;

        //2. 第一個隊伍篩選之後隻要前3個人;
        Stream<String> os1 = o.stream().filter(name -> name.length() == 3).limit(3);


        List<String> t = new ArrayList<>();
        t.add("古力娜紮");
        t.add("張無忌");
        t.add("張三豐");
        t.add("趙麗穎");
        t.add("張二狗");
        t.add("張天愛");
        t.add("張三");
        //擷取第二個隊伍的流對象


        //3. 第二個隊伍隻要姓張的成員姓名;

        //4. 第二個隊伍篩選之後不要前2個人;

       Stream<String> ts1 = t.stream().filter(name -> name.startsWith("張")).skip(2);

        //5. 将兩個隊伍合并為一個隊伍;
        Stream<String> ots = Stream.concat(os1, ts1);


        //6. 列印整個隊伍的姓名資訊
        ots.forEach(name-> System.out.println(name));


    }
}      

/*

Stream綜合案例

1. 第一個隊伍隻要名字為3個字的成員姓名;

2. 第一個隊伍篩選之後隻要前3個人;

3. 第二個隊伍隻要姓張的成員姓名;

4. 第二個隊伍篩選之後不要前2個人;

5. 将兩個隊伍合并為一個隊伍;

6. 列印整個隊伍的姓名資訊。