Java8新特性之Stream (3)

在介绍 collect 操作中,我们用了 Collectors 中提供的 toList 方法将结果汇总成List,collect 是很常用的操作Collectors中有很多有用的方法值得熟悉一下,其实很多终端方法都是 collect 的快捷写法,如果都不能满足需求我们还可以自己实现一个

转常用集合 // 转list List<String> collect = Stream.of("1", "2", "3").collect(Collectors.toList()); // 转set Set<String> collect = Stream.of("1", "2", "3").collect(Collectors.toSet()); // 转map,key为字符串长度,value为字符串本身 Map<Integer, String> collect = Stream.of("1", "2", "3") .collect(Collectors.toMap(String::length, Function.identity())); // 转并发版map,key为字符串长度,value为字符串本身 Map<Integer, String> collect = Stream.of("1", "2", "3") .collect(Collectors.toConcurrentMap(String::length, Function.identity())); // 转指定类型集合 ArrayList<String> collect = Stream.of("1", "2", "3") .collect(Collectors.toCollection(ArrayList::new)); 拼接字符串 // 拼接成一个字符串 String collect = Stream.of("1", "2", "3").collect(Collectors.joining()); // 拼接成一个字符串,逗号分隔 String collect = Stream.of("1", "2", "3").collect(Collectors.joining(",")); 统计

都有对应简化版,一些更加灵活多变的操作可以用Collectors

// 和终端操作中的 max 等价 Stream.of("1", "2", "3").collect(Collectors.maxBy(Comparator.naturalOrder())); // 和终端操作中的 min 等价 Stream.of("1", "2", "3").collect(Collectors.minBy(Comparator.naturalOrder())); // 和终端操作中的 sum 等价 Stream.of("1", "2", "3").collect(Collectors.counting(Integer::valueOf)); // 和数值流终端操作中的 sum 等价 Stream.of("1", "2", "3").collect(Collectors.summingInt(Integer::valueOf)); // 和数值流终端操作中的 average 等价 Stream.of("1", "2", "3").collect(Collectors.averagingInt(Integer::valueOf)); // 和数值流终端操作中的 summaryStatistics 等价 Stream.of("1", "2", "3").collect(Collectors.summarizingInt(Integer::valueOf)); 分组

可以和其他收集器方法任意组合

// 以字符串长度分成3组,map的key为长度,value为对应长度字符串list Map<Integer, List<String>> collect = Stream.of("1", "22", "33", "4", "555") .collect(Collectors.groupingBy(String::length)); // 以字符串长度分成3组,map的key为长度,value为对应的元素个数 Map<Integer, Long> collect = Stream.of("1", "22", "33", "4", "555") .collect(Collectors.groupingBy(String::length, Collectors.counting())); // 这个例子没有实际意义,展示我们可以进行二级分组,长度分组完毕,再组内以hash值分组 Map<Integer, Map<Integer, List<String>>> collect = Stream.of("1", "22", "33", "4", "555") .collect(Collectors.groupingBy( String::length, Collectors.groupingBy(String::hashCode) )); 分区

分区时特殊的分组,使用方法类似,特殊是通过谓词表达式只能分成两组,true是一组,false是一组

// 以长度大于2为标准分区 Map<Boolean, List<String>> collect = Stream.of("1", "22", "33", "4", "555") .collect(Collectors.partitioningBy(s -> s.length() > 2)); 归约 // 和终端操作 reduce 等价 Stream.of("1", "22", "33", "4", "555") .collect(Collectors.reducing(0, Integer::valueOf, Integer::sum)) 多操作连接 // 把流汇总成list,然后再求出其容量 Integer collect = Stream.of("1", "22", "33", "4", "555") .collect(Collectors.collectingAndThen(Collectors.toList(), List::size)); 自定义

有些时候默认的实现有缺陷,或者追求更高的性能我们需要自己实现收集器。只要实现 Collector<T, A , R>接口 中的方法我们就可以获得自己的收集器,其中 T 是元素泛型,A是累加器结果,R是最终返回结果,所有首先我们来看下要实现哪些方法

supplier:提供一个容器 A 装结果

accumulator:累加器,将元素累加进刚才创建的容器

combiner:合并容器的结果

finisher:完成操作,将 A 转为 R 返回

characteristics:是个定义标识的方法

UNORDERED:结果不受流中项目的遍历和累积顺序的影响

CONCURRENT:accumulator函数可以从多个线程同时调用

IDENTITY_FINISH:表示 finisher 没做任何事情,直接返回了累加的结果,也就是A和R相同

public static final Collector<String, List<String>, List<String>> myToList = Collector.of( // supplier: 创建 A(ArrayList) ArrayList::new, // accumulator:把每个元素放入 A 中 (list, el) -> list.add(el), // combiner:如果并行拆分成多个流,直接 addAll 合并 // 如果不想支持并行可以写个空,或抛UnsupportedOperationException异常 (listA, listB) -> { listA.addAll(listB); return listA; }, // finisher:不做任何事情,直接返回 A Function.identity(), // characteristics...:表名 A R 类型相同, 且支持并行流 Collector.Characteristics.IDENTITY_FINISH, Collector.Characteristics.CONCURRENT ); // 自定义收集器转成list List<String> collect = Stream.of("1", "22", "33", "4", "555").collect(myToList);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygjpd.html