你的浏览器不支持canvas

做你害怕做的事情,然后你会发现,不过如此。

Java8的流处理Stream使用实例

时间: 作者: 黄运鑫

本文章属原创文章,未经作者许可,禁止转载,复制,下载,以及用作商业用途。原作者保留所有解释权。


生成流 Stream

  • 集合有两个方法来生成流,创建串行流stream()和创建并行流parallelStream()
  • 串行流和并行流实例:

      @Test
      public void test() throws Exception {
          List<Integer> list = Arrays.asList(1, 2, 3);
          //串行流的操作
          list.stream().filter(item -> item == 2).collect(Collectors.toList());
          //并行流的操作
          list.parallelStream().filter(item -> item == 2).collect(Collectors.toList());
      }
    
  • 串行流和并行流的区别
    • 串行流是按照集合的顺序,依次操作集合中的元素。
    • 并行流是多线程执行,将集合切分成几个线程同时执行并一同返回结果,执行速度更快。
  • 实例如下:

      @Test
      public void test() throws Exception {
          List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
          //串行流的操作,输出结果123456789
          list.stream().forEach(item -> System.out.print(item));
          //并行流的操作,输出结果653471829,每次输出都不同
          list.parallelStream().forEach(item -> System.out.print(item));
      }
    

forEach

  • forEach用来迭代流中的每个元素。

      @Test
      public void test() throws Exception {
          List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
          //输出结果123456789
          list.stream().forEach(item -> System.out.print(item));
      }
    

map

  • map方法用于映射流中的每个元素,可以修改或重新定义集合中的元素。

      @Test
      public void test() throws Exception {
          List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
          //将每条数据加1
          List<Integer> collect1 = list.stream().map(item -> ++item).collect(Collectors.toList());
          //将大于5的数据减1
          List<Integer> collect2 = list.stream()
                  .map(item -> {
                      if (item > 5) {
                          return --item;
                      }
                      return item;
                  }).collect(Collectors.toList());
          //将personList改为只有用户名的list
          List<Person> personList = personList;
          List<String> userNameList = personList.stream().map(item -> item.getUserName()).collect(Collectors.toList());
      }
    

filter

  • filter 方法用于过滤元素。

      @Test
      public void test() throws Exception {
          List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
          //过滤掉大于5的元素,只保留小于等于5的元素。
          list.stream().filter(item -> item <= 5).collect(Collectors.toList());
      }
    

limit

  • limit 用于指定流中元素的数量。

      @Test
      public void test() throws Exception {
          List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
          //打印出前5条数据,输出结果12345
          list.stream().limit(5).forEach(item -> System.out.print(item));
      }
    

sorted

  • sorted 用于给流中元素排序。

      @Test
      public void test() throws Exception {
          //直接按元素的值升序、降序
          List<Integer> list = Arrays.asList(3, 1, 2);
          list.stream().sorted();
          list.stream().sorted(Comparator.reverseOrder());
          //如果list中是对象,按对象中的某个值升序、降序
          List<SysUser> sysUserList = new ArrayList<>();
          sysUserList.stream().sorted(Comparator.comparing(SysUser::getId));
          sysUserList.stream().sorted(Comparator.comparing(SysUser::getId).reversed());
      }
    

Collectors

  • Collectors 是一个归约操作,可以将流的结果归约为list集合、set集合、map集合、值。

      @Test
      public void test() throws Exception {
          //初始化三个用户,属性为:用户id、姓名、年龄
          List<SysUser> list = new ArrayList<>();
          list.add(new SysUser(1L, "张三", 18));
          list.add(new SysUser(2L, "李四", 20));
          list.add(new SysUser(3L, "王五", 18));
            
          //将以上用户按照年龄分组,两种写法
          Map<Integer, List<SysUser>> groupMap1 = list.stream().collect(Collectors.groupingBy(item -> item.getAge()));
          Map<Integer, List<SysUser>> groupMap2 = list.stream().collect(Collectors.groupingBy(BaseAutoIncrementEntity::getAge));
            
          //得到所有用户名并用逗号隔开,两种写法
          String userNameJoin1 = list.stream().map(item -> item.getUserName()).collect(Collectors.joining(","));
          String userNameJoin2 = list.stream().map(SysUser::getUserName).collect(Collectors.joining(","));
            
          //list转map,map的key是用户id,value是用户名(默认为HashMap)
          Map<Long, String> map = list.stream().collect(Collectors.toMap(SysUser::getId, SysUser::getUserName));
            
          //得到用户id的set集合(默认为HashSet),两种写法
          Set<Long> set1 = list.stream().map(item -> item.getId()).collect(Collectors.toSet());
          Set<Long> set2 = list.stream().map(BaseAutoIncrementEntity::getId).collect(Collectors.toSet());
            
          //计算用户年龄的和,两种写法
          Integer sumAge1 = list.stream().collect(Collectors.summingInt(SysUser::getAge));
          Integer sumAge2 = list.stream().mapToInt(SysUser::getAge).sum();
            
          //计算用户年龄的平均值
          Double aveAge = list.stream().collect(Collectors.averagingInt(SysUser::getAge));
            
          //计算最小年龄的用户,两种写法
          Optional<SysUser> minAge1 = list.stream().collect(Collectors.minBy(Comparator.comparing(SysUser::getAge)));
          Optional<SysUser> minAge2 = list1.stream().min(Comparator.comparing(SysUser::getAge));
            
            
          //计算最小年龄的用户,两种写法
          Optional<SysUser> maxAge1 = list.stream().collect(Collectors.maxBy(Comparator.comparing(SysUser::getAge)));
          Optional<SysUser> maxAge2 = list1.stream().max(Comparator.comparing(SysUser::getAge));
      }
    

统计

  • 对类型为intdoublelong的元素进行统计。

      @Test
      public void test() throws Exception {
          //对年龄进行统计
          IntSummaryStatistics stats = list.stream().mapToInt(SysUser::getAge).summaryStatistics();
          //最大年龄
          System.out.println(stats.getMax());
          //最小年龄
          System.out.println(stats.getMin());
          //年龄之和
          System.out.println(stats.getSum());
          //平均年龄
          System.out.println(stats.getAverage());
      }
    
  • 对类型为BigDecimal的元素进行统计。

      @Test
      public void test() throws Exception {
          //对changeBalance进行累加
          BigDecimal result = list.stream().map(UserBalanceLog::getChangeBalance)
                              .reduce(BigDecimal.ZERO,BigDecimal::add);
      }
    

对于本文内容有问题或建议的小伙伴,欢迎在文章底部留言交流讨论。