学习笔记-Java8新特性-第四节-StreamAPI

StreamAPI

  • 利用StreamAPI可以像流水线一样操作处理数据源(数组、集合……)

  • Stream自己不会存储元素

  • Stream不会改变数据源,而是会返回一个持有处理结构的新Stream

  • Steam操作时延迟执行的,他们会等到需要结果的时候才执行

    • 称为惰性求值

Stream操作的三个步骤

  • 创建Stream

    • 一个数据源(如:集合、数组),获取一个流
  • 中间操作

    • 一个中间操作链,对数据源的数据进行处理
  • 终止操作

    • 一个终止操作,执行中间操作链,并产生结果

创建Stream

  • 通过Collection系列集合提供的stream()或paralleStream()

    •         List<String> list = new ArrayList<>();
              Stream<String> stream = list.stream();
      
  • 通过Arrays中的静态方法stream()获取数组流

    •         Employee[] employees = new Employee[10];
              Stream<Employee> stream1 = Arrays.stream(employees);
      
  • 通过Stream类中的静态方法of()

    •         Stream<String> stream2 = Stream.of("aa", "bb", "cc");
      
  • 创建无限流

    •         //1.迭代
              //获取正偶数的无限流
              Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2);
              stream3.limit(10).forEach(System.out::println);
      
              //2.生成
              //获取随机数
              Stream.generate(() -> Math.random())
                      .limit(5)
                      .forEach(System.out::println);
      

中间操作

筛选与切片

  • filter——接收断言型Lambda,从流中排除某些元素

    •     public void test1() {
              //过滤,保留年龄大于35的员工
              employees.stream()
                      .filter((e) -> {
                          System.out.println("StreamAPI的中间操作");
                          return e.getAge() > 35;
                      })
                      .forEach(System.out::println);
          }
      
  • limit——截断流,使其元素不超过给定数量

    •     public void test2() {
              //截取,保留2个
              employees.stream()
                      .limit(2)
                      .forEach(System.out::println);
          }
      
  • skip——跳过,扔掉前n个元素

    •     public void test3() {
              //跳过,扔掉前2个
              employees.stream()
                      .skip(2)
                      .forEach(System.out::println);
          }
      
  • distinct——去重,通过hashCode()和equals()判断是否相等

    •     @Test
          public void test4() {
              //去重
              employees.stream()
                      .distinct()
                      .forEach(System.out::println);
          }
      

映射

  • map——接受一个Lambda,将元素转换成其他形式或提取信息

    • 接收一个函数作为参数,该函数会被应用到每个元素上,并映射成一个新的元素

    •     public void test5() {
              List<String> list = Arrays.asList("aa", "bb", "ccc", "ddd", "eee");
      
              list.stream()
                      .map((s) -> s.toUpperCase())
                      .forEach(System.out::println);
      
              System.out.println("_________________");
      
              employees.stream()
                      .map(Employee::getName)
                      .forEach(System.out::println);
      
          }
      
  • flatMap

    • 接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连接成一个流

    •     public void test6() {
              List<String> list = new ArrayList<>();
              list.add("aaa");
              list.add("bbb");
      
              list.stream()
                      //返回值为Stream<Stream<Character>>
                      .map(TestStreamAPI2::filterCharacter)
                      .forEach((characterStream) -> {
                          characterStream.forEach(System.out::println);
                      });
      
              System.out.println("------------------------");
      
              list.stream()
                      //返回值为Stream<Character>
                      .flatMap(TestStreamAPI2::filterCharacter)
                      .forEach(System.out::println);
          }
      
          public static Stream<Character> filterCharacter(String str) {
              List<Character> list = new ArrayList<>();
      
              for(Character ch : str.toCharArray()) {
                  list.add(ch);
              }
      
              return list.stream();
          }
      

排序

  • sorted()——自然排序(Comparable)

  • sorted(Comparator cmp)——定制排序

  •     public void test7() {
            List<String> list = Arrays.asList("bbb", "aaa", "ddd", "eee", "ccc");
    
            list.stream()
                    .sorted()
                    .forEach(System.out::println);
    
            System.out.println("---------------------");
    
            employees.stream()
                    .sorted((e1, e2) -> {
                        if(e1.getAge() == e2.getAge()) {
                            return e1.getName().compareTo(e2.getName());
                        } else {
                            return Integer.compare(e1.getAge(), e2.getAge());
                        }
                    })
                    .forEach(System.out::println);
    
        }
    

终止操作

查找与匹配

  • allMatch——检查是否匹配所有元素

  • anyMatch——检查是狗至少匹配一个元素

  • noneMatch——检查是否没有匹配所有元素

  • findFirst——返回第一个元素

  • findAny——返回当前流中的任意元素

    •     List<Employee> employees = Arrays.asList(
                  new Employee("张三", 18, 9999.99, Employee.Status.FREE),
                  new Employee("李四", 38, 5555.55, Employee.Status.BUSY),
                  new Employee("王五", 50, 6666.66, Employee.Status.VOCATION),
                  new Employee("赵六", 16, 3333.33, Employee.Status.FREE),
                  new Employee("田七", 8, 7777.77, Employee.Status.BUSY)
          );
      
          @Test
          public void test1() {
              boolean b1 = employees.stream()
                      .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
              System.out.println(b1);
      
              boolean b2 = employees.stream()
                      .anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
              System.out.println(b2);
      
              boolean b3 = employees.stream()
                      .noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
              System.out.println(b3);
      
              Optional<Employee> first = employees.stream()
                      .sorted(Comparator.comparingDouble(Employee::getSalary))
                      .findFirst();
              System.out.println(first);
      
              Optional<Employee> any = employees.parallelStream()
                      .filter((e) -> e.getStatus().equals(Employee.Status.BUSY))
                      .findAny();
              System.out.println(any);
      
          }
      
  • count——返回流中元素的总个数

  • max——返回流中的最大值

  • min——返回流中的最小值

    •     public void test2() {
              long count = employees.stream()
                      .count();
              System.out.println(count);
      
              Optional<Employee> max = employees.stream()
                      .max(Comparator.comparingDouble(Employee::getSalary));
              System.out.println(max);
      
              Optional<Double> min = employees.stream()
                      .map(Employee::getSalary)
                      .min(Double::compare);
              System.out.println(min);
          }
      

规约

  • reduce(T identity, BinaryOperator) / reduce(BinaryOperator)

    • 将流中的元素反复结合起来,得到一个值

    • identity代表一个初始值

    •     public void test3() {
              List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
      
              Integer sum = list.stream()
                      .reduce(0, Integer::sum);
              System.out.println(sum);
      
              System.out.println("-------------------");
      
              Optional<Double> op = employees.stream()
                      .map(Employee::getSalary)
                      .reduce(Double::sum);
              System.out.println(op.get());
          }
      

收集

  • collect——将流转换为其他形式

    • 接收一个Collector接口的实现

      • 使用对应的静态类Collectors提供的静态方法,可以方便地创建Collector实例
    • 用于给Stream中元素做汇总的方法

    •     public void test4() {
              List<String> list = employees.stream()
                      .map(Employee::getName)
                      .collect(Collectors.toList());
              list.forEach(System.out::println);
      
              System.out.println("------------------");
      
              Set<String> set = employees.stream()
                      .map(Employee::getName)
                      .collect(Collectors.toSet());
              set.forEach(System.out::println);
      
              System.out.println("------------------");
      
              HashSet<Employee.Status> hashSet = employees.stream()
                      .map(Employee::getStatus)
                      .collect(Collectors.toCollection(HashSet::new));
              hashSet.forEach(System.out::println);
      
          }
      
    •     public void test5() {
              Double avg = employees.stream()
                      .collect(Collectors.averagingDouble(Employee::getSalary));
              System.out.println(avg);
      
              System.out.println("_________________________");
      
              Double sum = employees.stream()
                      .collect(Collectors.summingDouble(Employee::getSalary));
      
          }
      
    •     @Test
          public void test6() {
              // 分组
              Map<Employee.Status, List<Employee>> collect = employees.stream()
                      .collect(Collectors.groupingBy(Employee::getStatus));
              System.out.println(collect);
      
              // 多级分组
              Map<Employee.Status, Map<String, List<Employee>>> collect1 = employees.stream()
                      .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
                          if (e.getAge() <= 35) {
                              return "青年";
                          } else if (e.getAge() <= 50) {
                              return "中年";
                          } else {
                              return "老年";
                          }
                      })));
              System.out.println(collect1);
      
          }
      
    •     public void test7() {
              // 分区
              Map<Boolean, List<Employee>> collect = employees.stream()
                      .collect(Collectors.partitioningBy((e) -> e.getSalary() > 5000));
              System.out.println(collect);
          }
      
    •     public void test8() {
              // 统计
              DoubleSummaryStatistics statistics = employees.stream()
                      .collect(Collectors.summarizingDouble(Employee::getSalary));
      
              System.out.println(statistics.getSum());
              System.out.println(statistics.getAverage());
              System.out.println(statistics.getMax());
          }
      
    •     public void test9() {
              // 字符串处理
              String collect = employees.stream()
                      .map(Employee::getName)
                      .collect(Collectors.joining(",", "===", "==="));
              System.out.println(collect);
              // ===张三,李四,王五,赵六,田七===
          }
      

并行流与顺序流

  • 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流

  • 底层使用到了Fork/Join框架

    • 使用了工作窃取模式

      • 将小任务分成了数个线程队列

      • 当某个线程队列处理完成后,会从其他没有完成的线程队列末尾偷取任务

Fork/Join

  • 可以使用parallel方法将流切换到并行模式

  • 提高工作效率

posted @   0Andl0  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示