最近工作中需要用到在一个乘机人列表中先按照乘机人类型分类,在对分组后的元素属性进行聚合,以达到一个 K -> V => ADT -> 张三;李四;王五,这样的Map结构,(其实就是不想用filter过滤在join),但是普通常用的流收集器是达不到这样的效果的,最后经过研究Collector并且参考资料后总结自定义一个收集器来操作运转,话不多说了,贴代码
先贴一份demo demo代码
复制代码
1
2
3
4
5
6
7
8
9
10
11
12// Bean对象,模拟 @Data @Accessors(chain = true) class TestBean { public String name; public Integer age; public String passengerType; public LocalDate localDate; public LocalDateTime localDateTime; public LocalTime localTime; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77@Test public void test() { /** * Collector有五个函数式接口 * 1、Supplier<A> supplier(); * 这个是一个初始化函数,用来定义一个中间操作收集器,比如 ArrayList * * 2、BiConsumer<A, T> accumulator(); * 这个就是收集器操作了 * * 3、BinaryOperator<A> combiner(); * 这个是多线程情况下合并收集器的操作,比如 ArrayList.addAll,将输入元素合并到结果容器中 * * 4、Function<A, R> finisher(); * 这个是一个结束操作,也就是下流收集器,合并两个结果容器(并行流使用,将多个线程产生的结果容器合并) * * 5、Set<Characteristics> characteristics(); */ Collector<TestBean, long[], Long> collector = new Collector<>() { @Override public Supplier<List<String>> supplier() { System.out.println("supplier invoked"); return new Supplier<List<String>>() { @Override public List<String> get() { // 定义一个收集器,用来保存所有的姓名 // 这里使用匿名内部类是为了在学习阶段更好的理解 // 不然一开始就用lambda的话我保证你的头会炸裂,后面会有lambda简化的代码 return new ArrayList<>(); } }; } @Override public BiConsumer<List<String>, TestBean> accumulator() { System.out.println("accumulator invoked"); return new BiConsumer<List<String>, TestBean>() { @Override public void accept(List<String> strings, TestBean testBean) { // 中间收集时的添加操作 strings.add(testBean.getName()); } }; } @Override public BinaryOperator<List<String>> combiner() { System.out.println("combiner invoked"); // 这里时并行的合并,用lambda可以表达为 (l1, l2) -> l1.addAll(l2) 再把l1 return出去 // 但是我这里没有用并行,就没操作了 return null; } @Override public Function<List<String>, String> finisher() { System.out.println("finisher invoked"); return new Function<List<String>, String>() { @Override public String apply(List<String> strings) { // 结尾的收集操作,这里就把list给合并了,用的hutool工具类 return StrUtil.join(",", strings); } }; } @Override public Set<Characteristics> characteristics() { System.out.println("characteristics invoked"); // return Collections.unmodifiableSet(EnumSet // .of(Collector.Characteristics.IDENTITY_FINISH)); return Collections.emptySet(); } }; System.err.println(sl.toString()); }
看一看lambda版本
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44@Test public void test4() { List<TestBean> testBeanList = new ArrayList<>(); testBeanList.add(new TestBean().setName("name1").setPassengerType("ADT").setAge(1)); testBeanList.add(new TestBean().setName("name2").setPassengerType("ADT").setAge(1)); testBeanList.add(new TestBean().setName("name3").setPassengerType("INF").setAge(2)); testBeanList.add(new TestBean().setName("name4").setPassengerType("INF").setAge(1)); testBeanList.add(new TestBean().setName("name5").setPassengerType("CLD").setAge(2)); testBeanList.add(new TestBean().setName("name6").setPassengerType("CLD").setAge(3)); testBeanList.add(new TestBean().setName("name7").setPassengerType("ADT").setAge(3)); Collector<TestBean, List<String>, String> collector = new Collector<TestBean, List<String>, String>() { @Override public Supplier<List<String>> supplier() { return ArrayList::new; } @Override public BiConsumer<List<String>, TestBean> accumulator() { return (list1, bean) -> list1.add(bean.getName()); } @Override public BinaryOperator<List<String>> combiner() { return (list1, list2) -> { list1.addAll(list2); return list1; }; } @Override public Function<List<String>, String> finisher() { return (list) -> StrUtil.join(";", list); } @Override public Set<Characteristics> characteristics() { return Collections.EMPTY_SET; } }; Map<String, String> collect = testBeanList.stream().collect(Collectors.groupingBy(TestBean::getPassengerType, collector)); System.out.println(collect); // 结果:{INF=name3;name4, ADT=name1;name2;name7, CLD=name5;name6} }
因为平时工作经常用到
Map<Integer, Long> collect = testBeanList.stream().collect(Collectors.groupingBy(TestBean::getAge, Collectors.counting()));
这个分组统计数量,索性也就自己手写了一份简单版的统计
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40@Test public void test3() { List<TestBean> testBeanList = new ArrayList<>(); testBeanList.add(new TestBean().setName("name1").setPassengerType("ADT").setAge(1)); testBeanList.add(new TestBean().setName("name2").setPassengerType("ADT").setAge(1)); testBeanList.add(new TestBean().setName("name3").setPassengerType("INF").setAge(2)); testBeanList.add(new TestBean().setName("name4").setPassengerType("INF").setAge(1)); testBeanList.add(new TestBean().setName("name5").setPassengerType("CLD").setAge(2)); testBeanList.add(new TestBean().setName("name6").setPassengerType("CLD").setAge(3)); testBeanList.add(new TestBean().setName("name7").setPassengerType("ADT").setAge(3)); Collector<TestBean, long[], Long> collector = new Collector<>() { @Override public Supplier<long[]> supplier() { return () -> new long[1]; } @Override public BiConsumer<long[], TestBean> accumulator() { return (res, bean) -> res[0] += 1; } @Override public BinaryOperator<long[]> combiner() { return (longs1, longs2) -> new long[]{(longs1[0] + longs2[0])}; } @Override public Function<long[], Long> finisher() { return longs -> longs[0]; } @Override public Set<Characteristics> characteristics() { return Collections.emptySet(); } }; Map<String, Long> collect = testBeanList.stream().collect(Collectors.groupingBy(TestBean::getPassengerType, collector)); System.out.println(collect); }
再贴一下简化版:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20@Test public void test5() { List<TestBean> testBeanList = new ArrayList<>(); testBeanList.add(new TestBean().setName("刘一").setPassengerType("ADT").setAge(1)); testBeanList.add(new TestBean().setName("周二").setPassengerType("ADT").setAge(1)); testBeanList.add(new TestBean().setName("林三").setPassengerType("INF").setAge(2)); testBeanList.add(new TestBean().setName("李四").setPassengerType("INF").setAge(1)); testBeanList.add(new TestBean().setName("王五").setPassengerType("CLD").setAge(2)); testBeanList.add(new TestBean().setName("赵六").setPassengerType("CLD").setAge(3)); testBeanList.add(new TestBean().setName("张七").setPassengerType("ADT").setAge(3)); Map<String, String> collect = testBeanList.stream().collect(Collectors.groupingBy(TestBean::getPassengerType, Collector.of( (Supplier<ArrayList<String>>) ArrayList::new, (ls, dto) -> ls.add(dto.getName()), (ls1, ls2) -> { ls1.addAll(ls2); return ls1; }, ls -> StrUtil.join(";", ls)))); System.out.println(collect); // {INF=林三;李四, ADT=刘一;周二;张七, CLD=王五;赵六} }
折腾了大半天,最后贴一下资料参考大佬的博客地址https://blog.csdn.net/xiliunian/article/details/88773718
最后
以上就是魁梧盼望最近收集整理的关于Java8 新特性 Colletor 收集器自定义的全部内容,更多相关Java8内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复