使用java 8 Stream

使用java 8 Stream

java8中stream是对集合(Collection)对象的功能上的增强。提供对集合高效的聚合和过滤操作。支持串行和并行两种模式进行汇聚操作。stream并非集合元素,并不会保存数据,如同迭代器一样,单向的不可往复的,遍历一次即用尽。而与迭代器不同的是,stream可以进行并行操作。

stream的构成:

使用流的过程基本分为:数据来源(source)->数据转换->执行结果。每次执行转换后原有的stream不变,返回一个新的stream,致使操作形成链,变成一个管道。

数据源的来源:

  • 集合对象Collection和数组
  • Collection.stream()
  • Collection.parallelStream()
  • Arrays.stream(T array)
  • Stream.of()

流的三种操作:

  • Intermediate:一个流可以进行零个或多个转换操作,目的就是打开流,执行某种过滤或map映射等返回一个新流,交给下一个操作使用。此类操作都是惰性化的,就是说仅仅调用这个方法并没有开始流的遍历。map/filter/distinct/sorted/peek/limit/skip/parallel/sequential/unordered
  • Terminal:结果操作,一个流只能有一个该操作,当执行该操作,流就相当于被使用光了,不会再产生其他流,并且会生成一个结果。forEach/toArray/reduce/collect/min/max/count/anyMatch/allMatch/noneMatch/findFirst/findAny/limit
  • short-circuiting:对于一个无限大的stream,在有限的时间内计算出结果或返回一个新的stream。anyMatch/allMatch/noneMatch/findFirst/findAny/limit

常见操作:

  • map:映射,map生成的是1:1的映射,每次输入的元素都会按照规则转换成另外一种规则的元素。

    /**
     * 简单收集,收集某属性集合
     */
    public Set<String> collectDate(List<UserVO> userList){
      return userList.stream().map(UserVO::getUserName).collect(Collectors.toSet());
    }
    
  • flatMap:一对多映射,通常用于合并流操作

      Stream<List<Integer>> inputStream = Stream.of(
       Arrays.asList(1),
       Arrays.asList(2, 3),
       Arrays.asList(4, 5, 6)
       );
      Stream<Integer> outputStream = inputStream.
      flatMap((childList) -> childList.stream());
    
  • filter:filter对原始的stream进行某测试,通过测试的元素形成一个新的stream

      /**
       * 简单过滤查找列表
       * @param userList
       * @param age
       * @return
       */
      public List<UserVO> simpleFilterFindList(List<UserVO> userList,int age){
        return userList.stream().filter((userVO)->userVO.getAge()==age).collect(Collectors.toList());
      }
    
  • forEach:接受lambda表达式,然后在流的每个元素执行表达式

  • findFirst:该操作是Terminal操作又是short-circuiting操作。总是返回集合的第一个元素的Optional

    /**
     * 查找第一个
     * @param userList
     * @return
     */
    public UserVO simpleFilter(List<UserVO> userList,String userName){
      return userList.stream().filter((userVO)->userVO.getUserName().equals(userName)).findFirst().orElse(null);
    }
    
  • reduce:该操作主要是将stream元素组合起来,提供一个起始值,然后依照规则跟前面的stream的各个元素的组合。

      // 字符串连接,concat = "ABCD"
      String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat); 
      // 求最小值,minValue = -3.0
      double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min); 
      // 求和,sumValue = 10, 有起始值
      int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
      // 求和,sumValue = 10, 无起始值
      sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
      // 过滤,字符串连接,concat = "ace"
      concat = Stream.of("a", "B", "c", "D", "e", "F").
       filter(x -> x.compareTo("Z") > 0).
       reduce("", String::concat);
    
  • limit/skip:limit是返回stream的前n个元素,而skip则是对其stream的前n个元素

      /**
       * limit 是取前n个元素
       * skip是丢弃前n个元素
       * @param userList
       * @return
       */
      public List<UserVO> limitAndSkip(List<UserVO> userList){
        return userList.stream().limit(10).skip(2).collect(Collectors.toList());
      }
    
  • sorted:对stream的排序,好处是可以先对stream进行其他操作如map,filter,limit等操作再进行排序

    /**
     * 排序集合
     * @param userList
     * @return
     */
    public List<UserVO> sortList(List<UserVO> userList){
      return userList.stream().sorted((t1,t2) -> t1.getUserName().compareTo(t2.getUserName())).collect(Collectors.toList());
    }
    
  • min/max/distinct:常见的取最大值最小值和去重操作

  • Match:allMatch/anyMatch/noneMatch,这些都是不需要遍历完所有元素就可以返回结果的,例如allMatch有一个不满足就会返回false。

    /**
     * 检查是否所有元素都匹配条件
     * @param userList
     * @return
     */
    public boolean matchAllUser(List<UserVO> userList){
      return userList.stream().allMatch((userVO)->userVO.getAge()>=0);
    }
    
  • 自定义生成流:Stream.generate
    通过Supplier接口可以自定义流的生成,常用于随机数,常量或者前后保持某种关系的流。必须使用limit控制流的大小。

      /**
       * 自定义流
       */
      public void generateStream(){
        Random ran = new Random();
        Supplier<Integer> stream = ran::nextInt;
        Stream.generate(stream).limit(10).forEach((value) -> System.out.println(value));
      }
    
  • Stream.iterate:操作与reduce类似,接受一个初始值,和一个操作,依次执行下去。也需要使用limit进行控制流的大小。

  • groupingBy:分组

    /**
     * 将集合分组
     * 根据年龄分组
     * @param userList
     * @return
     */
    public Map<Integer,List<UserVO>> groupUserVO(List<UserVO> userList){
      return userList.stream().collect(Collectors.groupingBy(userVO -> userVO.getAge()));
    }
    
  • partitioningBy:分割

    /**
     * 分割数据集,用年龄分割
     * @param userList
     * @return
     */
    public Map<Boolean,List<UserVO>> splitUserList(List<UserVO> userList){
      return userList.stream().collect(Collectors.partitioningBy(userVO -> userVO.getAge()>15));
    }
    

总结

  • 流不进行存储,不是一种数据结构,也不会修改底层的数据源,只会产生新的流
  • Intermediate操作永远是惰性的,很多操作是向后延迟,直到知到多少数据才会开始
  • stream可以并行处理,无需编写多线程代码
  • stream可以是无限的,但一般需要limit和findFirst等short-curcutiting方法快速得到结果

相关:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值