Collector

Collector是专门用来作为Stream的collect方法的参数的。

public interface Stream<T> extends BaseStream<T, Stream<T>> {<R, A> R collect(Collector<? super T, A, R> collector);
}

而Collectors是作为生产具体Collector的工具类。

Collector主要包含五个参数,它的行为也是由这五个参数来定义的,如下所示:

public interface Collector<T, A, R> {// supplier参数用于生成结果容器,容器类型为ASupplier<A> supplier();// accumulator用于消费元素,也就是归纳元素,这里的T就是元素,它会将流中的元素一个一个与结果容器A发生操作BiConsumer<A, T> accumulator();// combiner用于两个两个合并并行执行的线程的执行结果,将其合并为一个最终结果ABinaryOperator<A> combiner();// finisher用于将之前整合完的结果R转换成为AFunction<A, R> finisher();// characteristics表示当前Collector的特征值,这是个不可变SetSet<Characteristics> characteristics();
}

Collector拥有两个of方法用于生成Collector实例,其中一个拥有上面所有五个参数,另一个四个参数,不包括finisher。

public interface Collector<T, A, R> {// 四参方法,用于生成一个Collector,T代表流中的一个一个元素,R代表最终的结果public static<T, R> Collector<T, R, R> of(Supplier<R> supplier,BiConsumer<R, T> accumulator,BinaryOperator<R> combiner,Characteristics... characteristics) {/*...*/}// 五参方法,用于生成一个Collector,T代表流中的一个一个元素,A代表中间结果,R代表最终结果,finisher用于将A转换为R                                          public static<T, A, R> Collector<T, A, R> of(Supplier<A> supplier,BiConsumer<A, T> accumulator,BinaryOperator<A> combiner,Function<A, R> finisher,Characteristics... characteristics) {/*...*/}
}

Characteristics:这个特征值是一个枚举,拥有三个值:CONCURRENT(多线程并行),UNORDERED(无序),IDENTITY_FINISH(无需转换结果)。其中四参of方法中没有finisher参数,所以必有IDENTITY_FINISH特征值。

collect常见参数

toCollection:将流中的元素全部放置到一个集合中返回,这里使用Collection,泛指多种集合

public class CollectorsTest {public static void toCollectionTest(List<String> list) {List<String> ll = list.stream().collect(Collectors.toCollection(LinkedList::new));}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");toCollectionTest(list);}
}

toList:将流中的元素放置到一个列表集合中去。这个列表默认为ArrayList

public class CollectorsTest {public static void toListTest(List<String> list) {List<String> ll = list.stream().collect(Collectors.toList());}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");toListTest(list);}
}

toSet:将流中的元素放置到一个无序集set中去。默认为HashSet。

public class CollectorsTest {public static void toSetTest(List<String> list) {Set<String> ss = list.stream().collect(Collectors.toSet());}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");toSetTest(list);}
}

joining:joining的目的是将流中的元素全部以字符序列的方式连接到一起,可以指定连接符,甚至是结果的前后缀。

public class CollectorsTest {public static void joiningTest(List<String> list){// 无参方法String s = list.stream().collect(Collectors.joining());System.out.println(s);// 指定连接符String ss = list.stream().collect(Collectors.joining("-"));System.out.println(ss);// 指定连接符和前后缀String sss = list.stream().collect(Collectors.joining("-","S","E"));System.out.println(sss);}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");joiningTest(list);}
}

执行结果:

1234567891101212121121asdaa3e3e3e2321eew
123-456-789-1101-212121121-asdaa-3e3e3e-2321eew
S123-456-789-1101-212121121-asdaa-3e3e3e-2321eewE

mapping:这个映射是首先对流中的每个元素进行映射,即类型转换,然后再将新元素以给定的Collector进行归纳。

public class CollectorsTest {public static void mapingTest(List<String> list){List<Integer> ll = list.stream().limit(5).collect(Collectors.mapping(Integer::valueOf,Collectors.toList()));}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");mapingTest(list);//[123, 456, 789, 1101, 212121121]}
}

collectingAndThen:该方法是在归纳动作结束之后,对归纳的结果进行再处理。

public class CollectorsTest {public static void collectingAndThenTest(List<String> list){int length = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(),e -> e.size()));System.out.println(length);}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");collectingAndThenTest(list);//8}
}

counting:该方法用于计数。

public class CollectorsTest {public static void countingTest(List<String> list){long size = list.stream().collect(Collectors.counting());System.out.println(size);}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");countingTest(list);//8}
}

minBy/maxBy:生成一个用于获取最小/最大值的Optional结果的Collector。

public class CollectorsTest {public static void maxByAndMinByTest(List<String> list){System.out.println(list.stream().collect(Collectors.maxBy((a,b) -> a.length()-b.length())));System.out.println(list.stream().collect(Collectors.minBy((a,b) -> a.length()-b.length())));}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");//Optional[212121121]//Optional[123]maxByAndMinByTest(list);}
}

summingInt/summingLong/summingDouble:生成一个用于求元素和的Collector,首先通过给定的mapper将元素转换类型,然后再求和。参数的作用就是将元素转换为指定的类型,最后结果与转换后类型一致。

public class CollectorsTest {public static void summingTest(List<String> list){int i = list.stream().limit(3).collect(Collectors.summingInt(Integer::valueOf));long l = list.stream().limit(3).collect(Collectors.summingLong(Long::valueOf));double d = list.stream().limit(3).collect(Collectors.summingDouble(Double::valueOf));System.out.println(i +"\n" +l + "\n" + d);//1368 1368 1368.0}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");summingTest(list);}
}

averagingInt/averagingLong/averagingDouble:生成一个用于求元素平均值的Collector,首选通过参数将元素转换为指定的类型。参数的作用就是将元素转换为指定的类型,求平均值涉及到除法操作,结果一律为Double类型。

public class CollectorsTest {public static void averagingTest(List<String> list){double i = list.stream().limit(3).collect(Collectors.averagingInt(Integer::valueOf));double l = list.stream().limit(3).collect(Collectors.averagingLong(Long::valueOf));double d = list.stream().limit(3).collect(Collectors.averagingDouble(Double::valueOf));System.out.println(i +"\n" +l + "\n" + d);//456.0 456.0 456.0}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");averagingTest(list);}
}

reducing:reducing方法有三个重载方法,其实是和Stream里的三个reduce方法对应的,二者是可以替换使用的,作用完全一致,也是对流中的元素做统计归纳作用。

public final class Collectors {// 无初始值的情况,返回一个可以生成Optional结果的Collectorpublic static <T> Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op) {/*...*/}// 有初始值的情况,返回一个可以直接产生结果的Collectorpublic static <T> Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op) {/*...*/}// 有初始值,还有针对元素的处理方案mapper,生成一个可以直接产生结果的Collector,元素在执行结果操作op之前需要先执行mapper进行元素转换操作public static <T, U> Collector<T, ?, U> reducing(U identity,Function<? super T, ? extends U> mapper,BinaryOperator<U> op) {/*...*/}
}
public class CollectorsTest {public static void reducingTest(List<String> list){System.out.println(list.stream().limit(4).map(String::length).collect(Collectors.reducing(Integer::sum)));//Optional[13]System.out.println(list.stream().limit(3).map(String::length).collect(Collectors.reducing(0, Integer::sum)));//9System.out.println(list.stream().limit(4).collect(Collectors.reducing(0,String::length,Integer::sum)));//13}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");reducingTest(list);}
}

groupingBy:这个方法是用于生成一个拥有分组功能的Collector,它也有三个重载方法:

public final class Collectors {// 只需一个分组参数classifier,内部自动将结果保存到一个map中,每个map的键为?类型(即classifier的结果类型),值为一个list,这个list中保存在属于这个组的元素。public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier) {/*...*/}// 在上面方法的基础上增加了对流中元素的处理方式的Collector,比如上面的默认的处理方法就是Collectors.toList()public static <T, K, A, D>Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,Collector<? super T, A, D> downstream) {/*...*/}// 在第二个方法的基础上再添加了结果Map的生成方法。public static <T, K, D, A, M extends Map<K, D>>Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,Supplier<M> mapFactory,Collector<? super T, A, D> downstream) {/*...*/}
}
public class CollectorsTest {public static void groupingByTest(List<String> list){Map<Integer,List<String>> s = list.stream().collect(Collectors.groupingBy(String::length));Map<Integer,List<String>> ss = list.stream().collect(Collectors.groupingBy(String::length, Collectors.toList()));Map<Integer,Set<String>> sss = list.stream().collect(Collectors.groupingBy(String::length,HashMap::new,Collectors.toSet()));//{3=[123, 456, 789], 4=[1101], 5=[asdaa], 6=[3e3e3e], 7=[2321eew], 9=[212121121]}//{3=[123, 456, 789], 4=[1101], 5=[asdaa], 6=[3e3e3e], 7=[2321eew], 9=[212121121]}//{3=[123, 456, 789], 4=[1101], 5=[asdaa], 6=[3e3e3e], 7=[2321eew], 9=[212121121]}System.out.println(s.toString() + "\n" + ss.toString() + "\n" + sss.toString());}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");groupingByTest(list);}
}

partitioningBy:该方法将流中的元素按照给定的校验规则的结果分为两个部分,放到一个map中返回,map的键是Boolean类型,值为元素的列表List。

该方法有两个重载方法:

public final class Collectors {// 只需一个校验参数predicatepublic static <T>Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {/*...*/}// 在上面方法的基础上增加了对流中元素的处理方式的Collector,比如上面的默认的处理方法就是Collectors.toList()public static <T, D, A>Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,Collector<? super T, A, D> downstream) {/*...*/}
}
public class CollectorsTest {public static void partitioningByTest(List<String> list){Map<Boolean,List<String>> map = list.stream().collect(Collectors.partitioningBy(e -> e.length()>5));Map<Boolean,Set<String>> map2 = list.stream().collect(Collectors.partitioningBy(e -> e.length()>6,Collectors.toSet()));//{false=[123, 456, 789, 1101, asdaa], true=[212121121, 3e3e3e, 2321eew]}//{false=[123, 456, 1101, 789, 3e3e3e, asdaa], true=[212121121, 2321eew]}System.out.println(map.toString() + "\n" + map2.toString());}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");partitioningByTest(list);}
}

toMap:toMap方法是根据给定的键生成器和值生成器生成的键和值保存到一个map中返回,键和值的生成都依赖于元素,可以指定出现重复键时的处理方案和保存结果的map。

public final class Collectors {// 指定键和值的生成方式keyMapper和valueMapperpublic static <T, K, U>Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper) {/*...*/}// 在上面方法的基础上增加了对键发生重复时处理方式的mergeFunction,比如上面的默认的处理方法就是抛出异常public static <T, K, U>Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction) {/*...*/}// 在第二个方法的基础上再添加了结果Map的生成方法。public static <T, K, U, M extends Map<K, U>>Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction,Supplier<M> mapSupplier) {/*...*/}
}
public class CollectorsTest {public static void toMapTest(List<String> list){Map<String,String> map = list.stream().limit(3).collect(Collectors.toMap(e -> e.substring(0,1),e -> e));Map<String,String> map1 = list.stream().collect(Collectors.toMap(e -> e.substring(0,1),e->e,(a,b)-> b));Map<String,String> map2 = list.stream().collect(Collectors.toMap(e -> e.substring(0,1),e->e,(a,b)-> b,HashMap::new));//{1=123, 4=456, 7=789}//{a=asdaa, 1=1101, 2=2321eew, 3=3e3e3e, 4=456, 7=789}//{a=asdaa, 1=1101, 2=2321eew, 3=3e3e3e, 4=456, 7=789}System.out.println(map.toString() + "\n" + map1.toString() + "\n" + map2.toString());}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");toMapTest(list);}
}

第一种方式中,如果不添加limit限制,就会抛出异常。

还有并发的版本:toConcurrentMap,同样三种重载方法,与toMap基本一致,只是它最后使用的map是并发Map:ConcurrentHashMap。

summarizingInt/summarizingLong/summarizingDouble:这三个方法适用于汇总的,返回值分别是IntSummaryStatistics,LongSummaryStatistics,DoubleSummaryStatistics。在这些返回值中包含有流中元素的指定结果的数量、和、最大值、最小值、平均值。所有仅仅针对数值结果。

public class CollectorsTest {public static void summarizingTest(List<String> list){IntSummaryStatistics intSummary = list.stream().collect(Collectors.summarizingInt(String::length));LongSummaryStatistics longSummary = list.stream().limit(4).collect(Collectors.summarizingLong(Long::valueOf));DoubleSummaryStatistics doubleSummary = list.stream().limit(3).collect(Collectors.summarizingDouble(Double::valueOf));//IntSummaryStatistics{count=8, sum=40, min=3, average=5.000000, max=9}//LongSummaryStatistics{count=4, sum=2469, min=123, average=617.250000, max=1101}//DoubleSummaryStatistics{count=3, sum=1368.000000, min=123.000000, average=456.000000, max=789.000000}System.out.println(intSummary.toString() + "\n" + longSummary.toString() + "\n" + doubleSummary.toString());}public static void main(String[] args) {List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");summarizingTest(list);}
}

整个Collectors工具类就是在为Collector服务,用于创建各种不同的Collector。部分功能与Stream中的方法重合了,为了简化代码,完全不必采用Collectors实现,优先Stream方法。

java8之stream流之Collector和Collectors相关推荐

  1. Java8特性 stream流常用方法

    Java8特性 stream流常用方法 Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据. Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方 ...

  2. Java8中Stream流对集合操作

    java8中Stream流引入函数式编程思想,主要配合各种接口.lambda表达式.方法引用等方式,为集合的遍历.过滤.映射等提供非常"优雅"的操作方式. Student.java ...

  3. Java8种Stream流相关操作——集合的筛选、归约、分组、聚合

    过滤.筛选   filter skip /*** 过滤 筛选*/@Testpublic void test2(){List<String> list = Arrays.asList(&qu ...

  4. Java8的 Stream 流的各种用法

    Java8 的 Stream 流的各种用法 什么是Stream 1. Stream可以由数组或集合创建,对流的操作分为两种 2. Stream的特性 3. Stream可以通过集合数组创建 4. st ...

  5. java8中stream流解决两个list合并问题

    当我们遇到需要将两个list合并成一个list实体的时候,可以使用java8的stream流来解决,以下是我的一个小demo,可供大家参考学习. public ResultDto listBalanc ...

  6. Java8 的 Stream 流式操作之王者归来

    相对于Java8之前的Java的相关操作简直是天差地别,Java8 的流式操作的出现,也很大程度上改变了开发者对于Java的繁琐的操作的印象,从此,Java也走向了函数式编程的道路! 1 流的创建 1 ...

  7. 利用java8特性Stream流对list集合进行多个属性组装数据

    需求很简单,将list的数据放入另一个list属性而组装成数据 主要用到的方法是java8之list集合中取出某一属性: List<String> names=list.stream(). ...

  8. java8使用stream流将list转map

    stream将list转化为map 在Stream流中将List转换为Map,是使用Collectors.toMap方法来进行转换. 1.key和value都是对象中的某个属性值. Map<St ...

  9. java8的stream流操作的数据结构

    在java8的流操作中分为终止符和非终止符. 非终止符不会触发数据的处理. 每次通过stream()方法新建立一个流的时候都会创建一个Head类.这个类是ReferencePipeline的一个内部类 ...

最新文章

  1. gdbserver yum 安装_linux gdb怎么安装?
  2. Practical Lessons from Predicting Clicks on Ads at Facebook (2014)论文阅读
  3. JdbcType类型和Java类型的对应关系
  4. Swift傻傻分不清楚系列(十二) 属性
  5. ctype函数_PHP Ctype(字符类型)函数
  6. 如何用sbt新建akka项目
  7. mysql编码丢了_记住:永远不要在 MySQL 中使用 UTF-8
  8. 力扣46. 全排列(JavaScript)
  9. springboot启动图标_SpringBoot基础教程
  10. shell脚本实时监控进程连接数
  11. iOS 内存泄漏的常见场景
  12. asp 文本转时间_ASP.NET Core界面开发,DevExpress v19.2增强富文本编辑器功能
  13. redis 经典36问
  14. 7月29日绝地求生服务器维护,绝地求生7月29日更新到几点_绝地求生2020年7月29日更新维护时间安排一览_三六五吃鸡...
  15. 软件打不开且显示乱码的解决办法
  16. 小型微型计算机怎么样,电脑小主机怎么样,全方位分析小型电脑主机优缺点
  17. PRT电波拉皮的原理, 做电波拉皮效果好吗能维持多久
  18. Node-RED使用指南:28:撤销与删除恢复
  19. opencv 图像金字塔及图像重建、融合
  20. 【音视频处理】为什么MP3不是无损音乐?音频参数详解,码率、采样率、音频帧、位深度、声道、编码格式的关系

热门文章

  1. 手机游戏运营必备的数据分析指标
  2. 真无线蓝牙耳机哪个延迟最低?2023延迟超低的蓝牙耳机推荐
  3. matlab legend函数 用法
  4. 深入理解:为什么要使用工厂模式?
  5. 使用bootstarp前端组件集成的table 分页组件 ;简单上手使用实现前端分页功能
  6. 一种 Windows IOCP 整合 OpenSSL 实现方案
  7. Jsp学习笔记——第二天
  8. 66. 【大学】恭喜发财 利是窦来
  9. c语言文件读写ppt,c语言文件读写.ppt
  10. OleDbCommand OleDbDataAdapter比较研究素材