【重學Java】Stream流


Stream流

體驗Stream流【理解】

  • 案例需求

    按照下面的要求完成集合的創建和遍歷

    • 創建一個集合,存儲多個字符串元素
    • 把集合中所有以"張"開頭的元素存儲到一個新的集合
    • 把"張"開頭的集合中的長度為3的元素存儲到一個新的集合
    • 遍歷上一步得到的集合
  • 原始方式示例代碼

  public class StreamDemo {
      public static void main(String[] args) {
          //創建一個集合,存儲多個字符串元素
          ArrayList<String> list = new ArrayList<String>();

          list.add("林青霞");
          list.add("張曼玉");
          list.add("王祖賢");
          list.add("柳岩");
          list.add("張敏");
          list.add("張無忌");

          //把集合中所有以"張"開頭的元素存儲到一個新的集合
          ArrayList<String> zhangList = new ArrayList<String>();

          for(String s : list) {
              if(s.startsWith("張")) {
                  zhangList.add(s);
              }
          }

  //        System.out.println(zhangList);

          //把"張"開頭的集合中的長度為3的元素存儲到一個新的集合
          ArrayList<String> threeList = new ArrayList<String>();

          for(String s : zhangList) {
              if(s.length() == 3) {
                  threeList.add(s);
              }
          }

  //        System.out.println(threeList);

          //遍歷上一步得到的集合
          for(String s : threeList) {
              System.out.println(s);
          }
          System.out.println("--------");

          //Stream流來改進
          list.stream().filter(s -> s.startsWith("張")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));

      }
  }
  • Stream流的好處

    • 直接閱讀代碼的字面意思即可完美展示無關邏輯方式的語義:獲取流、過濾姓張、過濾長度為3、逐一打印
    • Stream流把真正的函數式編程風格引入到Java中
    • 代碼簡潔

Stream流的常見生成方式【應用】

  • Stream流的思想

image

  • Stream流的三類方法

    • 獲取Stream流
      • 創建一條流水線,並把數據放到流水線上准備進行操作
    • 中間方法
      • 流水線上的操作
      • 一次操作完畢之后,還可以繼續進行其他操作
    • 終結方法
      • 一個Stream流只能有一個終結方法
      • 是流水線上的最后一個操作
  • 生成Stream流的方式

    • Collection體系集合(單列集合)

      使用默認方法stream()生成流, default Stream stream()

    • Map體系集合(雙列集合)

      把Map轉成Set集合,間接的生成流

    • 數組

      通過Arrays中的靜態方法stream生成流

    • 同種數據類型的多個數據

      通過Stream接口的靜態方法of(T... values)生成流

  • 代碼演示

  public class StreamDemo {
      public static void main(String[] args) {
          //Collection體系的集合可以使用默認方法stream()生成流
          List<String> list = new ArrayList<String>();
          Stream<String> listStream = list.stream();
  
          Set<String> set = new HashSet<String>();
          Stream<String> setStream = set.stream();
  
          //Map體系的集合間接的生成流
          Map<String,Integer> map = new HashMap<String, Integer>();
          Stream<String> keyStream = map.keySet().stream();
          Stream<Integer> valueStream = map.values().stream();
          Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();
  
          //數組可以通過Arrays中的靜態方法stream生成流
          String[] strArray = {"hello","world","java"};
          Stream<String> strArrayStream = Arrays.stream(strArray);
        
        	//同種數據類型的多個數據可以通過Stream接口的靜態方法of(T... values)生成流
          Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
          Stream<Integer> intStream = Stream.of(10, 20, 30);
      }
  }

Stream流中間操作方法【應用】

  • 概念

    中間操作的意思是,執行完此方法之后,Stream流依然可以繼續執行其他操作

  • 常見方法

    方法名 說明
    Stream filter(Predicate predicate) 用於對流中的數據進行過濾
    Stream limit(long maxSize) 返回此流中的元素組成的流,截取前指定參數個數的數據
    Stream skip(long n) 跳過指定參數個數的數據,返回由該流的剩余元素組成的流
    static Stream concat(Stream a, Stream b) 合並a和b兩個流為一個流
    Stream distinct() 返回由該流的不同元素(根據Object.equals(Object) )組成的流(自定義數據類型重寫equals和hashCode
  • filter原理

        ArrayList list = new ArrayList(List.of(1,2,3,4));
        list.stream().filter(new Predicate() {
            @Override
            public boolean test(Object o) {
                return false;
            }
        });
      //Predicate中有一個抽象方法test可以使用匿名內部類或者lambda表達式
	  //filter方法獲取流中的每一個數據
	  //而test中的s,依次表示流中的每一個數據
	  //我們只需要在流中對s進行判斷就行了
	  //如果判斷結果為true,則當前結果留下
	  //如果判斷結果為false,則當前結果不要
  • filter代碼演示
  public class StreamDemo01 {
      public static void main(String[] args) {
          //創建一個集合,存儲多個字符串元素
          ArrayList<String> list = new ArrayList<String>();

          list.add("林青霞");
          list.add("張曼玉");
          list.add("王祖賢");
          list.add("柳岩");
          list.add("張敏");
          list.add("張無忌");

          //需求1:把list集合中以張開頭的元素在控制台輸出
          list.stream().filter(s -> s.startsWith("張")).forEach(System.out::println);
          System.out.println("--------");

          //需求2:把list集合中長度為3的元素在控制台輸出
          list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
          System.out.println("--------");

          //需求3:把list集合中以張開頭的,長度為3的元素在控制台輸出
          list.stream().filter(s -> s.startsWith("張")).filter(s -> s.length() == 3).forEach(System.out::println);
      }
  }
  • limit&skip代碼演示
  public class StreamDemo02 {
      public static void main(String[] args) {
          //創建一個集合,存儲多個字符串元素
          ArrayList<String> list = new ArrayList<String>();

          list.add("林青霞");
          list.add("張曼玉");
          list.add("王祖賢");
          list.add("柳岩");
          list.add("張敏");
          list.add("張無忌");

          //需求1:取前3個數據在控制台輸出
          list.stream().limit(3).forEach(System.out::println);
          System.out.println("--------");

          //需求2:跳過3個元素,把剩下的元素在控制台輸出
          list.stream().skip(3).forEach(System.out::println);
          System.out.println("--------");

          //需求3:跳過2個元素,把剩下的元素中前2個在控制台輸出
          list.stream().skip(2).limit(2).forEach(System.out::println);
      }
  }
  • concat&distinct代碼演示
  public class StreamDemo03 {
      public static void main(String[] args) {
          //創建一個集合,存儲多個字符串元素
          ArrayList<String> list = new ArrayList<String>();
  
          list.add("林青霞");
          list.add("張曼玉");
          list.add("王祖賢");
          list.add("柳岩");
          list.add("張敏");
          list.add("張無忌");
  
          //需求1:取前4個數據組成一個流
          Stream<String> s1 = list.stream().limit(4);
  
          //需求2:跳過2個數據組成一個流
          Stream<String> s2 = list.stream().skip(2);
  
          //需求3:合並需求1和需求2得到的流,並把結果在控制台輸出
  //        Stream.concat(s1,s2).forEach(System.out::println);
  
          //需求4:合並需求1和需求2得到的流,並把結果在控制台輸出,要求字符串元素不能重復
          Stream.concat(s1,s2).distinct().forEach(System.out::println);
      }
  }

Stream流終結操作方法【應用】

  • 概念

    終結操作的意思是,執行完此方法之后,Stream流將不能再執行其他操作

  • 常見方法

    方法名 說明
    void forEach(Consumer action) 獲取流的每個元素並對其執行操作
    long count() 返回此流中的元素數
  • 代碼演示

  public class StreamDemo {
      public static void main(String[] args) {
          //創建一個集合,存儲多個字符串元素
          ArrayList<String> list = new ArrayList<String>();
  
          list.add("林青霞");
          list.add("張曼玉");
          list.add("王祖賢");
          list.add("柳岩");
          list.add("張敏");
          list.add("張無忌");
  
          //需求1:把集合中的元素在控制台輸出
  	//list.stream().forEach(System.out::println);
	
  	//list.stream().forEach(new Consumer() {
    //          @Override
    //          public void accept(Object o) {
    //            
    //          }
    //      });
	//在forEach方法底層會循環調用流中每一個數據
	//並循環調用accept方法,把每一個數據傳遞給accept方法
	//s就依次代表流中的每一個數據
	//所以只需要在accept方法中編寫相應的業務邏輯即可
	
          //需求2:統計集合中有幾個以張開頭的元素,並把統計結果在控制台輸出
          long count = list.stream().filter(s -> s.startsWith("張")).count();
          System.out.println(count);
      }
  }

Stream流的收集操作【應用】

  • 概念

    對數據使用Stream流的方式操作完畢后,可以把流中的數據收集到集合中

  • 常用方法

    方法名 說明
    R collect(Collector collector) 把結果收集到集合中
  • 工具類Collectors提供了具體的收集方式

    方法名 說明
    public static Collector toList() 把元素收集到List集合中
    public static Collector toSet() 把元素收集到Set集合中
    public static Collector toMap(Function keyMapper,Function valueMapper) 把元素收集到Map集合中
  • 代碼演示

    • 單列集合
  ArrayList<Integer> list = new ArrayList<Integer>(List.of(1, 2, 3, 4,4,4));
  
        //filter負責過濾數據
        //collect負責收集數據
        //獲取流中剩余的數據,但是他不負責創建容器,也不負責把數據添加到容器中
        //Collectors.toList()會在底層創建一個List集合,並把所以的數據添加到List集合中。
		
        List<Integer> list1 = list.stream().filter(number -> number % 2 == 0).collect(Collectors.toList());
        System.out.println(list1);

        Set<Integer> set = list.stream().filter(number -> number % 2 == 0).collect(Collectors.toSet());
        System.out.println(set);
	//[2, 4, 4, 4]
	//[2, 4]
	```
	- 雙列集合
```java
  public static void main(String[] args) {
        /**
         * Steam流的收集方法
         *
         * 創建一個ArrayList集合,並添加以下的字符串,字符串中前面是姓名,后面是年齡
         * "zhangsan,23"
         * "lisi,24"
         * "wangwu,25"
         * 保留年齡大於等於24歲的人,並將結果收集到Map集合中,姓名為鍵,年齡為值
         */
        ArrayList<String> list = new ArrayList<>(List.of("zhangsan,23","lisi,24","wangwu,25"));
        Map<String,Integer> map = list.stream().filter((String s)->{
            String[] split = s.split(",");
            int i = Integer.parseInt(split[1]);
            return i>=24;
        }).collect(Collectors.toMap(
                (String s)-> {
                    return s.split(",")[0];
                },
                (String s)->{
                    return Integer.valueOf(s.split(",")[1]);
                }
        ));
        map.forEach((String s,Integer i)->{
            System.out.println(s+"---"+i);
        });
    }

Stream流綜合練習【應用】

  • 案例需求

image

  • 代碼實現

    演員類

  public class Actor {
      private String name;
  
      public Actor(String name) {
          this.name = name;
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          this.name = name;
      }
  }

測試類

  package com.cnblogs.gonghr;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.stream.Collectors;
  import java.util.stream.Stream;

  public class test13 {
    public static void main(String[] args) {
        String actor_man_one = "周潤發";
        String actor_man_two = "成龍";
        String actor_man_three = "劉德華";
        String actor_man_four = "吳京";
        String actor_man_five = "周星馳";
        String actor_man_six = "李連傑";
        ArrayList<String> actors_man = new ArrayList<>(List.of(actor_man_one, actor_man_two, actor_man_three, actor_man_four, actor_man_five, actor_man_six));
        String actor_woman_one = "林心如";
        String actor_woman_two = "張曼玉";
        String actor_woman_three = "楊超越";
        String actor_woman_four = "林志玲";
        String actor_woman_five = "周冬雨";
        String actor_woman_six = "楊穎";
        ArrayList<String> actors_woman = new ArrayList<>(List.of(actor_woman_one, actor_woman_two, actor_woman_three, actor_woman_four, actor_woman_five, actor_woman_six));
        Stream<String> actorStream_man= actors_man.stream().filter(actor -> actor.length() == 3).limit(2);
        Stream<String> actorStream_woman = actors_woman.stream().filter(actor -> actor.startsWith("楊")).skip(1);
        Stream.concat(actorStream_man, actorStream_woman).forEach(s->{
            Actor actor = new Actor(s);
            System.out.println(actor);
        });
    }
  }
  //Actor{name='周潤發'}
  //Actor{name='劉德華'}
  //Actor{name='楊穎'}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM