• Java之stream流的详细解析


    2.Stream流

    2.1体验Stream流【理解】

    • 案例需求

      按照下面的要求完成集合的创建和遍历

      • 创建一个集合,存储多个字符串元素

      • 把集合中所有以"张"开头的元素存储到一个新的集合

      • 把"张"开头的集合中的长度为3的元素存储到一个新的集合

      • 遍历上一步得到的集合

    • 原始方式示例代码

      1. public class MyStream1 {
      2.    public static void main(String[] args) {
      3.        //集合的批量添加
      4.        ArrayList list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));
      5.        //list.add()
      6.        //遍历list1把以张开头的元素添加到list2中。
      7.        ArrayList list2 = new ArrayList<>();
      8.        for (String s : list1) {
      9.            if(s.startsWith("张")){
      10.                list2.add(s);
      11.           }
      12.       }
      13.        //遍历list2集合,把其中长度为3的元素,再添加到list3中。
      14.        ArrayList list3 = new ArrayList<>();
      15.        for (String s : list2) {
      16.            if(s.length() == 3){
      17.                list3.add(s);
      18.           }
      19.       }
      20.        for (String s : list3) {
      21.            System.out.println(s);
      22.       }      
      23.   }
      24. }

    • 使用Stream流示例代码

      1. public class StreamDemo {
      2.    public static void main(String[] args) {
      3.        //集合的批量添加
      4.        ArrayList list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));
      5.        //Stream流
      6.        list1.stream().filter(s->s.startsWith("张"))
      7.               .filter(s->s.length() == 3)
      8.               .forEach(s-> System.out.println(s));
      9.   }
      10. }

    • Stream流的好处

      • 直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印

      • Stream流把真正的函数式编程风格引入到Java中

      • 代码简洁

    2.2Stream流的常见生成方式【应用】

    • Stream流的思想

    • Stream流的三类方法

      • 获取Stream流

        • 创建一条流水线,并把数据放到流水线上准备进行操作

      • 中间方法

        • 流水线上的操作

        • 一次操作完毕之后,还可以继续进行其他操作

      • 终结方法

        • 一个Stream流只能有一个终结方法

        • 是流水线上的最后一个操作

    • 生成Stream流的方式

      • Collection体系集合

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

      • Map体系集合

        把Map转成Set集合,间接的生成流

      • 数组

        通过Arrays中的静态方法stream生成流

      • 同种数据类型的多个数据

        通过Stream接口的静态方法of(T... values)生成流

    • 代码演示

      1. public class StreamDemo {
      2.    public static void main(String[] args) {
      3.        //Collection体系的集合可以使用默认方法stream()生成流
      4.        List list = new ArrayList();
      5.        Stream listStream = list.stream();
      6.        Set set = new HashSet();
      7.        Stream setStream = set.stream();
      8.        //Map体系的集合间接的生成流
      9.        Map map = new HashMap();
      10.        Stream keyStream = map.keySet().stream();
      11.        Stream valueStream = map.values().stream();
      12.        Stream> entryStream = map.entrySet().stream();
      13.        //数组可以通过Arrays中的静态方法stream生成流
      14.        String[] strArray = {"hello","world","java"};
      15.        Stream strArrayStream = Arrays.stream(strArray);
      16.      
      17.     //同种数据类型的多个数据可以通过Stream接口的静态方法of(T... values)生成流
      18.        Stream strArrayStream2 = Stream.of("hello", "world", "java");
      19.        Stream intStream = Stream.of(10, 20, 30);
      20.   }
      21. }

    2.3Stream流中间操作方法【应用】

    • 概念

      中间操作的意思是,执行完此方法之后,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) )组成的流
    • filter代码演示

      1. public class MyStream3 {
      2.    public static void main(String[] args) {
      3. //       Stream filter(Predicate predicate):过滤
      4. //       Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值
      5.        ArrayList list = new ArrayList<>();
      6.        list.add("张三丰");
      7.        list.add("张无忌");
      8.        list.add("张翠山");
      9.        list.add("王二麻子");
      10.        list.add("张良");
      11.        list.add("谢广坤");
      12.        //filter方法获取流中的 每一个数据.
      13.        //而test方法中的s,就依次表示流中的每一个数据.
      14.        //我们只要在test方法中对s进行判断就可以了.
      15.        //如果判断的结果为true,则当前的数据留下
      16.        //如果判断的结果为false,则当前数据就不要.
      17. //       list.stream().filter(
      18. //               new Predicate() {
      19. //                   @Override
      20. //                   public boolean test(String s) {
      21. //                       boolean result = s.startsWith("张");
      22. //                       return result;
      23. //                   }
      24. //               }
      25. //       ).forEach(s-> System.out.println(s));
      26.        //因为Predicate接口中只有一个抽象方法test
      27.        //所以我们可以使用lambda表达式来简化
      28. //       list.stream().filter(
      29. //               (String s)->{
      30. //                   boolean result = s.startsWith("张");
      31. //                       return result;
      32. //               }
      33. //       ).forEach(s-> System.out.println(s));
      34.        list.stream().filter(s ->s.startsWith("张")).forEach(s-> System.out.println(s));
      35.   }
      36. }

    • limit&skip代码演示

      1. public class StreamDemo02 {
      2.    public static void main(String[] args) {
      3.        //创建一个集合,存储多个字符串元素
      4.        ArrayList list = new ArrayList();
      5.        list.add("林青霞");
      6.        list.add("张曼玉");
      7.        list.add("王祖贤");
      8.        list.add("柳岩");
      9.        list.add("张敏");
      10.        list.add("张无忌");
      11.        //需求1:取前3个数据在控制台输出
      12.        list.stream().limit(3).forEach(s-> System.out.println(s));
      13.        System.out.println("--------");
      14.        //需求2:跳过3个元素,把剩下的元素在控制台输出
      15.        list.stream().skip(3).forEach(s-> System.out.println(s));
      16.        System.out.println("--------");
      17.        //需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
      18.        list.stream().skip(2).limit(2).forEach(s-> System.out.println(s));
      19.   }
      20. }

    • concat&distinct代码演示

      1. public class StreamDemo03 {
      2.    public static void main(String[] args) {
      3.        //创建一个集合,存储多个字符串元素
      4.        ArrayList list = new ArrayList();
      5.        list.add("林青霞");
      6.        list.add("张曼玉");
      7.        list.add("王祖贤");
      8.        list.add("柳岩");
      9.        list.add("张敏");
      10.        list.add("张无忌");
      11.        //需求1:取前4个数据组成一个流
      12.        Stream s1 = list.stream().limit(4);
      13.        //需求2:跳过2个数据组成一个流
      14.        Stream s2 = list.stream().skip(2);
      15.        //需求3:合并需求1和需求2得到的流,并把结果在控制台输出
      16. //       Stream.concat(s1,s2).forEach(s-> System.out.println(s));
      17.        //需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
      18.        Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s));
      19.   }
      20. }

    2.4Stream流终结操作方法【应用】

    • 概念

      终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作

    • 常见方法

      方法名说明
      void forEach(Consumer action)对此流的每个元素执行操作
      long count()返回此流中的元素数
    • 代码演示

      1. public class MyStream5 {
      2.    public static void main(String[] args) {
      3.        ArrayList list = new ArrayList<>();
      4.        list.add("张三丰");
      5.        list.add("张无忌");
      6.        list.add("张翠山");
      7.        list.add("王二麻子");
      8.        list.add("张良");
      9.        list.add("谢广坤");
      10.        //method1(list);
      11.        
      12. //       long count():返回此流中的元素数
      13.        long count = list.stream().count();
      14.        System.out.println(count);
      15.   }
      16.    private static void method1(ArrayList list) {
      17.        // void forEach(Consumer action):对此流的每个元素执行操作
      18.        // Consumer接口中的方法void accept(T t):对给定的参数执行此操作
      19.        //在forEach方法的底层,会循环获取到流中的每一个数据.
      20.        //并循环调用accept方法,并把每一个数据传递给accept方法
      21.        //s就依次表示了流中的每一个数据.
      22.        //所以,我们只要在accept方法中,写上处理的业务逻辑就可以了.
      23.        list.stream().forEach(
      24.                new Consumer() {
      25.                    @Override
      26.                    public void accept(String s) {
      27.                        System.out.println(s);
      28.                   }
      29.               }
      30.       );
      31.      
      32.        System.out.println("====================");
      33.        //lambda表达式的简化格式
      34.        //是因为Consumer接口中,只有一个accept方法
      35.        list.stream().forEach(
      36.               (String s)->{
      37.                    System.out.println(s);
      38.               }
      39.       );
      40.        System.out.println("====================");
      41.        //lambda表达式还是可以进一步简化的.
      42.        list.stream().forEach(s->System.out.println(s));
      43.   }
      44. }

    2.5 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集合中
    • 代码演示

      1. // toList和toSet方法演示
      2. public class MyStream7 {
      3.    public static void main(String[] args) {
      4.        ArrayList list1 = new ArrayList<>();
      5.        for (int i = 1; i <= 10; i++) {
      6.            list1.add(i);
      7.       }
      8.        list1.add(10);
      9.        list1.add(10);
      10.        list1.add(10);
      11.        list1.add(10);
      12.        list1.add(10);
      13.        //filter负责过滤数据的.
      14.        //collect负责收集数据.
      15.                //获取流中剩余的数据,但是他不负责创建容器,也不负责把数据添加到容器中.
      16.        //Collectors.toList() : 在底层会创建一个List集合.并把所有的数据添加到List集合中.
      17.        List list = list1.stream().filter(number -> number % 2 == 0)
      18.               .collect(Collectors.toList());
      19.        System.out.println(list);
      20.    Set set = list1.stream().filter(number -> number % 2 == 0)
      21.           .collect(Collectors.toSet());
      22.    System.out.println(set);
      23. }
      24. }
      25. /**
      26. Stream流的收集方法 toMap方法演示
      27. 创建一个ArrayList集合,并添加以下字符串。字符串中前面是姓名,后面是年龄
      28. "zhangsan,23"
      29. "lisi,24"
      30. "wangwu,25"
      31. 保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
      32. */
      33. public class MyStream8 {
      34. public static void main(String[] args) {
      35.     ArrayList list = new ArrayList<>();
      36.        list.add("zhangsan,23");
      37.        list.add("lisi,24");
      38.        list.add("wangwu,25");
      39.        Map map = list.stream().filter(
      40.                s -> {
      41.                    String[] split = s.split(",");
      42.                    int age = Integer.parseInt(split[1]);
      43.                    return age >= 24;
      44.               }
      45.         //   collect方法只能获取到流中剩余的每一个数据.
      46.         //在底层不能创建容器,也不能把数据添加到容器当中
      47.         //Collectors.toMap 创建一个map集合并将数据添加到集合当中
      48.          // s 依次表示流中的每一个数据
      49.          //第一个lambda表达式就是如何获取到Map中的键
      50.          //第二个lambda表达式就是如何获取Map中的值
      51.       ).collect(Collectors.toMap(
      52.                s -> s.split(",")[0],
      53.                s -> Integer.parseInt(s.split(",")[1]) ));
      54.        System.out.println(map);
      55. }
      56. }

  • 相关阅读:
    Spring注解@Qualifier的详细用法你知道几种「扩展点实战系列」- 第444篇
    正则表达式:掌握文本处理的秘密武器
    数据结构——常见链表算法题
    面试官:什么是Java内存模型?
    java8 .stream().map().collect() 的用法
    [SUCTF 2019]EasyWeb
    python之schedule
    Linux管道与重定向
    基于微信小程序的青少年素质教育培训系统设计与实现-计算机毕业设计源码+LW文档
    09 | Harbor中的镜像清除
  • 原文地址:https://blog.csdn.net/qq_69748833/article/details/132998995