java 1.8 Stream

  • stream:
    • 是数据渠道,用于操作数据源(数组,集合等.)所产生的元素序列
      • 集合讲的是数据,流讲的是计算.
      • 并行: parallel
    • 注意:
      • stram 自己不会存储元素.
      • stream 不会改变源对象,相反 他们会返回一个持有结果的新stream.
      • stream 操作是延迟执行的,这意味着他们会等到需要结果的时候才执行.
    • 使用步骤:
      • 1.创建stream
      • 2.中间操作
      • 3.终止操作
        • 注意:中间操作 不会执行任何操作,只有在终止操作的时候才会一次性执行.
        • 多个中间操作可以连接起来形成一个流水线,除非流水线上出发终止操作,否则中间操作不会执行任何处理.而在终止操作时一次性全部处理.称为 "惰性求值".
    • public static void main(String[] args) { //可以通过Collection系列集合提供的stream() 串行 或 parallelStream() 并行 List list = new ArrayList<>(); Stream stream = list.stream(); //通过Arrays中的静态方法stream()获取 数组流 LoginRequest[] loginRequests = new LoginRequest[10]; Stream stream1 = Arrays.stream(loginRequests); //通过stream类中的静态方法of() Stream aa = Stream.of("aa"); //创建 无限流 //迭代 Stream iterate = Stream.iterate(0, (x) -> x + 2); //iterate.limit(10) 就是中间操作 //forEach(System.out::println) 就是终止操作 iterate.limit(10).forEach(System.out::println); }

      【java 1.8 Stream】
    • 中间操作:
      • 筛选与切片
        • filter接收lambda, 从六中排除某些元素
        • limit截断流.使其元素不超过给定数量
        • skip(n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit互补
        • distinct 筛选(去重),通过流所生成元素的hashCode()和equals()去除重复元素
      • filter筛选:
        • static List loginRequests = Arrays.asList( new LoginRequest("张三", "1111", "11"), new LoginRequest("李四", "2222", "22"), new LoginRequest("王五", "3333", "33"), new LoginRequest("赵六", "6666", "66") ); /** * @Description: filter筛选 * @Param: [args] * @return: void * @Author: 单人影 * @Date: 2019/12/8 0008 15:59 */ public static void main(String[] args) { Stream loginRequestStream = loginRequests.stream().filter((e) -> "22".equals(e.getAge())); loginRequestStream.forEach(System.out::println); }


      • limit截断:
        • static List loginRequests = Arrays.asList( new LoginRequest("张三", "1111", "11"), new LoginRequest("李四", "2222", "22"), new LoginRequest("王五", "3333", "33"), new LoginRequest("赵六", "6666", "66") ); /** * @Description: limit截断 * @Param: [args] * @return: void * @Author: 单人影 * @Date: 2019/12/8 0008 15:59 */ public static void main(String[] args) { loginRequests.stream() .filter((e) -> Integer.valueOf(e.getAge()) > 11) .limit(2) .forEach(System.out::println); }控制台: LoginRequest{userName='李四', passWord='2222', age='22'} LoginRequest{userName='王五', passWord='3333', age='33'}


      • skip 跳过:
        • static List loginRequests = Arrays.asList( new LoginRequest("张三", "1111", "11"), new LoginRequest("李四", "2222", "22"), new LoginRequest("王五", "3333", "33"), new LoginRequest("赵六", "6666", "66") ); /** * @Description: skip 跳过 * @Param: [args] * @return: void * @Author: 单人影 * @Date: 2019/12/8 0008 15:59 */ public static void main(String[] args) { loginRequests.stream() .filter((e) -> Integer.valueOf(e.getAge()) > 11) .skip(2) .forEach(System.out::println); }控制台: LoginRequest{userName='赵六', passWord='6666', age='66'}


      • distinct 去重
        • static List loginRequests = Arrays.asList( new LoginRequest("张三", "1111", "11"), new LoginRequest("张三", "1111", "11"), new LoginRequest("张三", "1111", "11"), new LoginRequest("李四", "2222", "22"), new LoginRequest("王五", "3333", "33"), new LoginRequest("赵六", "6666", "66") ); /** * @Description: distinct 去重 * @Param: [args] * @return: void * @Author: 单人影 * @Date: 2019/12/8 0008 15:59 */ public static void main(String[] args) { loginRequests.stream() .filter((e) -> Integer.valueOf(e.getAge()) > 1) .distinct() .forEach(System.out::println); }要重写对象的equals和hashCode方法. 控制台: LoginRequest{userName='张三', passWord='1111', age='11'} LoginRequest{userName='李四', passWord='2222', age='22'} LoginRequest{userName='王五', passWord='3333', age='33'} LoginRequest{userName='赵六', passWord='6666', age='66'}


    • 映射:
      • map 接受lambda,讲元素转成其他形式或提取信息,接受一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素.
      • flagMap 接收一个函数作为参数,将流中的每一个值都转换成另一个流,然后把所有的流了解成一个流.
      • /** * @Description: 映射 map * @Param: [args] * @return: void * @Author: 单人影 * @Date: 2019/12/8 0008 15:59 */ public static void main(String[] args) { List list = Arrays.asList("aaa", "bbb", "ccc", "ddd"); list.stream().map((str) -> str.toUpperCase()).forEach(System.out::println); }控制台: AAA BBB CCC DDD/** * @Description: 映射 flatMap * @Param: [args] * @return: void * @Author: 单人影 * @Date: 2019/12/8 0008 15:59 */ public static void main(String[] args) { list.stream().map((str) -> str.toUpperCase()).forEach(System.out::println); System.out.println("----------------------------------"); //正常的map取值 Stream> streamStream = list.stream().map(Test::filter); //使用flatMap 都放到flagMap中 Stream characterStream = list.stream().flatMap(Test::filter); characterStream.forEach(System.out::println); }public static Stream filter(String string) { List list = new ArrayList(); for (Character character : string.toCharArray()) { list.add(character); } return list.stream(); }总结:map相当于把一个个流加到map这个大流中. flatMap 相当于把流中的一个个元素加到flatMap流中


    • 排序:
      • sorted()自然排序
      • sorted(Comparator com) 定制排序
      • static List loginRequests = Arrays.asList( new LoginRequest("张三", "1111", "11"), new LoginRequest("张三1", "1113", "11"), new LoginRequest("张三2", "1112", "11"), new LoginRequest("李四", "2222", "22"), new LoginRequest("王五", "3333", "33"), new LoginRequest("赵六", "6666", "66") ); static List list = Arrays.asList("aaa", "ccc", "ddd", "bbb"); /** * @Description: 排序 sorted * @Param: [args] * @return: void * @Author: 单人影 * @Date: 2019/12/8 0008 15:59 */ public static void main(String[] args) { list.stream().sorted().forEach(System.out::println); //控制台 aaa bbb ccc ddd loginRequests.stream().sorted((x, y) -> { //年龄相同 比密码 if (x.getAge().equals(y.getAge())) { return x.getPassWord().compareTo(y.getPassWord()); } else { //直接比年龄 return Integer.valueOf(x.getAge()).compareTo(Integer.valueOf(y.getAge())); //倒叙 return -Integer.valueOf(x.getAge()).compareTo(Integer.valueOf(y.getAge())); } } ).forEach(System.out::println); }控制台: LoginRequest{userName='张三', passWord='1111', age='11'} LoginRequest{userName='张三2', passWord='1112', age='11'} LoginRequest{userName='张三1', passWord='1113', age='11'} LoginRequest{userName='李四', passWord='2222', age='22'} LoginRequest{userName='王五', passWord='3333', age='33'} LoginRequest{userName='赵六', passWord='6666', age='66'}


    • 终止:
      • 查找与匹配:
        • allMatch 检查是否匹配所有元素
        • anyMatch 检查是否至少匹配一个元素
        • noneMatch 检查是否没有匹配的所有元素
        • findFirst 返回第一个元素
        • finaAny 返回当前流中的任意元素
        • count 返回流中元素的总个数
        • max 返回流中最大值
        • min 返回流中最小值
      • static List loginRequests = Arrays.asList( new LoginRequest("张三", "1111", "11"), new LoginRequest("张三1", "1113", "11"), new LoginRequest("张三2", "1112", "11"), new LoginRequest("李四", "2222", "22"), new LoginRequest("王五", "3333", "33"), new LoginRequest("赵六", "6666", "66") ); /** * @Description: 查找匹配 * @Param: [args] * @return: void * @Author: 单人影 * @Date: 2019/12/8 0008 15:59 */ public static void main(String[] args) { boolean b = loginRequests.stream().allMatch((x) -> x.getPassWord().equals("111111")); System.out.println(b); //其余的匹配用法基本相同//findFirst Optional optional = loginRequests.stream().sorted((x, y) -> x.getAge().compareTo(y.getAge())).findFirst(); //Optional是为了放置空指针 如果为空就用orElse()括号里面的. LoginRequest loginRequest1 = new LoginRequest("111", "222", "333"); LoginRequest loginRequest = optional.orElse(loginRequest1); System.out.println(loginRequest.toString()); }控制台: false LoginRequest{userName='张三', passWord='1111', age='11'}


    • 归约 reduce(T identity,BinaryOperator ) /reduct(BinaryOperator)可以将流中元素反复结合起来,得到一个值.
      • /** * @Description: 归约 reduce * @Param: [args] * @return: void * @Author: 单人影 * @Date: 2019/12/8 0008 15:59 */ public static void main(String[] args) { List list = Arrays.asList(1, 2, 3, 4, 5); Integer reduce = list.stream().reduce(0, (x, y) -> x + y); System.out.println(reduce); System.out.println("================================"); //有可能返回为空的都是Optional ,因为上面指定了起始值.不可能为空. Optional reduce1 = loginRequests.stream().map(LoginRequest::getUserName).reduce((x, y) -> x += (y)); System.out.println(reduce1); }控制台: 15 ================================ Optional[张三张三1张三2李四王五赵六]


    • 收集: collect 将流转换为其他形式,接受一个collector接口的实现,用于给stream中元素做汇总的方法. (分组)
      • static List loginRequests = Arrays.asList( new LoginRequest("张三", "1111", "11"), new LoginRequest("张三1", "1113", "11"), new LoginRequest("张三2", "1112", "11"), new LoginRequest("李四", "2222", "22"), new LoginRequest("王五", "3333", "33"), new LoginRequest("赵六", "6666", "66") ); static List list = Arrays.asList("aaa", "ccc", "ddd", "bbb"); /** * @Description: 收集 collect * @Param: [args] * @return: void * @Author: 单人影 * @Date: 2019/12/8 0008 15:59 */ public static void main(String[] args) { List collect = loginRequests.stream().map(LoginRequest::getUserName).collect(Collectors.toList()); System.out.println(collect.toString()); Set collects= loginRequests.stream().map(LoginRequest::getAge).collect(Collectors.toSet()); System.out.println(collects.toString()); //分组 groupingBy还可以多级分组 Map> collect1 = loginRequests.stream().collect(Collectors.groupingBy(LoginRequest::getAge)); System.out.println(collect1.toString()); //还可以分区.true一个区 false一个区 Collectors.partitioningBy //连接 Collectors.join()可以写成join(",") 逗号拼接}控制台: [张三, 张三1, 张三2, 李四, 王五, 赵六] [11, 22, 33, 66] {66=[LoginRequest{userName='赵六', passWord='6666', age='66'}], 33=[LoginRequest{userName='王五', passWord='3333', age='33'}], 22=[LoginRequest{userName='李四', passWord='2222', age='22'}], 11=[LoginRequest{userName='张三', passWord='1111', age='11'}, LoginRequest{userName='张三1', passWord='1113', age='11'}, LoginRequest{userName='张三2', passWord='1112', age='11'}]}

  • 使用示例:
    • list累加 BigDecimal allAssets = tradeBalanceCrmList.stream().filter(item -> item.getTotalProfit() != null).map(TradeBalanceCrmDto::getTotalProfit).reduce(BigDecimal.ZERO, BigDecimal::add); 分组 Map> productTypeGroupBy = tradeBalanceCrmList.stream().filter(item -> StringUtils.isNotEmpty(item.getProductType())).collect(Collectors.groupingBy(TradeBalanceCrmDto::getProductType)); 遍历 for (String key : productTypeGroupBy.keySet()) { if (ProductTypeEnum.PUBLICFUND.getCode().equals(key)) { publicList.addAll(productTypeGroupBy.get(key)); log.debug("公募:{},value:{}", productTypeGroupBy.get(key)); } else if (ProductTypeEnum.PRIVATEFUND.getCode().equals(key)) { privateList.addAll(productTypeGroupBy.get(key)); log.debug("似募:{},value:{}", productTypeGroupBy.get(key)); } }排序: Collections.sort(tradeAppFlowDtos, (o1, o2) -> o2.getAcceptTime().compareTo(o1.getAcceptTime())); 如果要按照升序排序, 则o1 小于o2,返回-1(负数),相等返回0,01大于02返回1(正数) 如果要按照降序排序 则o1 小于o2,返回1(正数),相等返回0,01大于02返回-1(负数)去除为空字段.返回list List collect = custManagerInfos.stream().filter((item) -> StringUtils.isNotEmpty(item.getFundManagerCode())).collect(Collectors.toList());


    • 双层for循环:
      • List tradeBalanceCrmDtos = tradeBalanceCrmExtendMapper.selectByConditionByCustId(custId); if (CollectionUtils.isEmpty(tradeBalanceCrmDtos)) { return tradeBalanceCrmDtos; } List list = new ArrayList<>(); TradeBalanceCrmDto tradeBalanceCrmDtoResult = null; for (TradeBalanceCrmDto tradeBalanceCrmDto : tradeBalanceCrmDtos) { boolean flag = list.stream().anyMatch(item -> item.getFundCode().equals(tradeBalanceCrmDto.getFundCode())); if (flag) { continue; } tradeBalanceCrmDtoResult = new TradeBalanceCrmDto(); BeanUtils.copyProperties(tradeBalanceCrmDto, tradeBalanceCrmDtoResult); List collect = tradeBalanceCrmDtos.stream().filter((item) -> tradeBalanceCrmDto.getFundCode().equals(item.getFundCode())).collect(Collectors.toList()); log.debug("归集的List为:{}", collect.toString()); tradeBalanceCrmDtoResult.setFundAsset(collect.stream().filter((item) -> item.getFundAsset() != null).map(TradeBalanceCrmDto::getFundAsset).reduce(BigDecimal.ZERO, (x, y) -> x.add(y))); tradeBalanceCrmDtoResult.setTotalBala(collect.stream().filter((item) -> item.getTotalBala() != null).map(TradeBalanceCrmDto::getTotalBala).reduce(BigDecimal.ZERO, (x, y) -> x.add(y))); tradeBalanceCrmDtoResult.setAvailBala(collect.stream().filter((item) -> item.getAvailBala() != null).map(TradeBalanceCrmDto::getAvailBala).reduce(BigDecimal.ZERO, (x, y) -> x.add(y))); tradeBalanceCrmDtoResult.setTotalProfit(collect.stream().filter((item) -> item.getTotalProfit() != null).map(TradeBalanceCrmDto::getTotalProfit).reduce(BigDecimal.ZERO, (x, y) -> x.add(y))); list.add(tradeBalanceCrmDtoResult); }


  • 常用示例:
    • //过滤不为空的list List collect = custManagerInfos.stream().filter((item) -> StringUtils.isNotEmpty(item.getFundManagerCode())).collect(Collectors.toList()); //非空 分组 Map> registarCodeMap = list.stream().filter(item -> StringUtils.isNotEmpty(item.getRegistrarCode())).collect(Collectors.groupingBy(TransferListVo::getRegistrarCode)); //非空 累加 BigDecimal allAssets = tradeBalanceCrmList.stream().filter(item -> item.getTotalProfit() != null).map(TradeBalanceCrmDto::getTotalProfit).reduce(BigDecimal.ZERO, BigDecimal::add);


    推荐阅读