概述
最近工作中需要用到在一个乘机人列表中先按照乘机人类型分类,在对分组后的元素属性进行聚合,以达到一个 K -> V => ADT -> 张三;李四;王五,这样的Map结构,(其实就是不想用filter过滤在join),但是普通常用的流收集器是达不到这样的效果的,最后经过研究Collector并且参考资料后总结自定义一个收集器来操作运转,话不多说了,贴代码
先贴一份demo demo代码
// 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;
}
@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版本
@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()));
这个分组统计数量,索性也就自己手写了一份简单版的统计
@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);
}
再贴一下简化版:
@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 新特性 Colletor 收集器自定义所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复