需求:

将 一个容器List<Bean> 按照一定的字段进行分组,分组过后的值为特定的BEAN 里面的属性例如:
假定有这样一个Bean
public class SubjectOberser{
private String subjectKey;
private AbstractObserver abstractObserver;
...geter seter 方法...
}
我们需要按照 subjectKey 进行分组,分组过后的内容 应该为这样一个容器Map<String,List<AbstractObserver>>
map 中的key,为SubjectOberser 属性的subjectKey,值为List<AbstractObserver>
实现过程
首先来看看collector 的接口定义
public interface Collector<T, A, R> {
Supplier<A> supplier();
BiConsumer<A, T> accumulator();
Function<A, R> finisher();
BinaryOperator<A> combiner();
Set<Characteristics> characteristics();
}
类型 T ,是在容器里面元素的类型
类型 A ,是accumulator 返回的类型,即是累加器的返回类型
类型 R ,是最终结果的类型
supplier 方法返回的结果必须为一个空的Supplier,也就是一个空的无参函数(签名就是这样的 ()->{}),在调用的时候它会创建一个空的累加器(accumulator)实例,供数据收集的时候使用,很明显如果按照我们的需求试下你自己collector 这里应该返回一个 () -> new HashMap<>() ,一个Map 来收集结果
accumulator 方法返回归约操作的函数(签名是这样的 (a,b)->void ),当遍历到流中第n个元素时,这个函数执行时会有两个参数:保存归约结果的累加器(已 收集了流中的前n-1个项目),还有第n个元素本身。签名也展示该函数是void,因为该操作是在原来的容器里面进行更新的,所以返回的是void 类型。按照需求的中的实现应该是是这样的:
public BiConsumer<Map<String, List<AbstractObserver>>, SubjectObserver> accumulator() {
return (Map<String, List<AbstractObserver>> acc, SubjectObserver v) -> {
if (acc.containsKey(v.getSubjectKey())){
acc.get(v.getSubjectKey()).add(v.getAbstractObserver());
}else{
List<AbstractObserver> l = new ArrayList<>();
l.add(v.getAbstractObserver());
acc.put(v.getSubjectKey(),l);
}
};
}
这里的逻辑就是if else 逻辑判断就是,这个key ,在map 中是否存在,如果不存在,那么我们需要给他new一个list 的实例,不然我的的数据没有地方存储
finisher 可从名字看出方法累积过程的最后要调用的一个函数,以便将累加器对象转换为整个集合操作的最终结果。通常来说累加器的类型也是返回的结果的类型,那么就返回identity 就可以了,如果不是的话,就行自行转换了。在当前需求的情况下我们的累加器和返回结果的类型是一致的,所以这里的实现是这样的:
public Function<Map<String, List<AbstractObserver>>,
Map<String, List<AbstractObserver>>> finisher(){
return Function.identity();
}
combiner 方法是将两个累加的结果进行一个合并的过程,当然这个过程并不是每一个collector 都会调用得到(后面会讲到)
按照我们的需求,只需要将两个累加器的,中间结果合并成为一个结果即可,所以是现实这样的:
public BinaryOperator<Map<String, List<AbstractObserver>>> combiner() {
return ((Map<String, List<AbstractObserver>> map1,
Map<String, List<AbstractObserver>> map2) -> {
map1.putAll(map2);
return map1;
});
}
characteristics 该方法返回一个 Characteristics 的集合,它有如下值可选
UNORDERED—— 归约结果不受流中项目的遍历和累积顺序的影响。
CONCURRENT—— accumulator函数可以从多个线程同时调用,且该收集器可以并行执行。如果收集器没有标为UNORDERED,那 它仅在用于用于无序数据源时才可以并行归约。
IDENTITY_ FINISH—— 这表明完成器方法返回的函数是一个不改变的函数,这种情况下,累加器对象将会直接用作合并过程 的最终结果。
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
}
最终collector 代码合在一起就是:
public class MyCollector implements Collector<SubjectObserver,
Map<String, List<AbstractObserver>>,
Map<String, List<AbstractObserver>>> {
@Override
public Supplier<Map<String, List<AbstractObserver>>> supplier() {
return () -> new HashMap<>();
}
@Override
public BiConsumer<Map<String, List<AbstractObserver>>, SubjectObserver> accumulator() {
return (Map<String, List<AbstractObserver>> acc, SubjectObserver v) -> {
if (acc.containsKey(v.getSubjectKey())) {
acc.get(v.getSubjectKey()).add(v.getAbstractObserver());
} else {
List<AbstractObserver> l = new ArrayList<>();
l.add(v.getAbstractObserver());
acc.put(v.getSubjectKey(), l);
}
};
}
@Override
public BinaryOperator<Map<String, List<AbstractObserver>>> combiner() {
return ((Map<String, List<AbstractObserver>> map1, Map<String, List<AbstractObserver>> map2) -> {
map1.putAll(map2);
return map1;
});
}
@Override
public Function<Map<String, List<AbstractObserver>>, Map<String, List<AbstractObserver>>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
}
}
调用的过程就是:
public static Map<String, List<AbstractObserver>> initObjectMap() {
ClassScaner classScaner = new ClassScaner();
Set<Class> set = classScaner.doScan("com.souche.datacenter.observer");
return set
.stream()
.filter(aClass -> SubjectAnnotationResolver.getAnnotationSubjectName(aClass) != null)
.map(aClass -> {
String subjectKey = SubjectAnnotationResolver.getAnnotationSubjectName(aClass);
AbstractObserver abstractObserver = getBeanByClassName(aClass.getSimpleName());
return new SubjectObserver(subjectKey, abstractObserver);
}).collect(new MyCollector());
}
直接在使用的地方直接new MyCollector 就可以了
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
# java8
# collector
# java
# 垃圾收集器
# Java9中新增的Collector收集器
# Java8 Stream Collectors收集器使用方法解析
# java收集器Collector案例汇总
# 累加器
# 是这样
# 是一个
# 是在
# 遍历
# 这样一个
# 值为
# 就可以
# 的是
# 情况下
# 收集器
# 也就
# 多个
# 将会
# 给他
# 只需
# 你自己
# 就行
# 不受
# 不存在
相关文章:
如何在新浪SAE免费搭建个人博客?
建站之星安装步骤有哪些常见问题?
威客平台建站流程解析:高效搭建教程与设计优化方案
网站好制作吗知乎,网站开发好学吗?有什么技巧?
枣阳网站制作,阳新火车站打的到仙岛湖多少钱?
北京建设网站制作公司,北京古代建筑博物馆预约官网?
香港服务器建站指南:免备案优势与SEO优化技巧全解析
广州营销型建站服务商推荐:技术优势与SEO优化解析
厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?
如何快速选择适合个人网站的云服务器配置?
如何用免费手机建站系统零基础打造专业网站?
如何选择域名并搭建高效网站?
上海制作企业网站有哪些,上海有哪些网站可以让企业免费发布招聘信息?
怀化网站制作公司,怀化新生儿上户网上办理流程?
如何在万网ECS上快速搭建专属网站?
广州美橙建站如何快速搭建多端合一网站?
招商网站制作流程,网站招商广告语?
如何在阿里云ECS服务器部署织梦CMS网站?
已有域名能否直接搭建网站?
如何优化Golang Web性能_Golang HTTP服务器性能提升方法
非常酷的网站设计制作软件,酷培ai教育官方网站?
小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?
义乌企业网站制作公司,请问义乌比较好的批发小商品的网站是什么?
网站制作新手教程,新手建设一个网站需要注意些什么?
活动邀请函制作网站有哪些,活动邀请函文案?
最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?
制作假网页,招聘网的薪资待遇,会有靠谱的吗?一面试又各种折扣?
建站之星伪静态规则如何正确配置?
平台云上自助建站如何快速打造专业网站?
建站主机选哪家性价比最高?
网站制作报价单模板图片,小松挖机官方网站报价?
移民网站制作流程,怎么看加拿大移民官网?
专业的网站制作设计是什么,如何制作一个企业网站,建设网站的基本步骤有哪些?
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
如何选择最佳自助建站系统?快速指南解析优劣
胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?
制作网站的过程怎么写,用凡科建站如何制作自己的网站?
北京制作网站的公司,北京铁路集团官方网站?
在线ppt制作网站有哪些,请推荐几个好的课件下载的网站?
网站制作的方法有哪些,如何将自己制作的网站发布到网上?
如何选择高效可靠的多用户建站源码资源?
西安制作网站公司有哪些,西安货运司机用的最多的app或者网站是什么?
平台云上自主建站:模板化设计与智能工具打造高效网站
新网站制作渠道有哪些,跪求一个无线渠道比较强的小说网站,我要发表小说?
建站主机选购指南:核心配置优化与品牌推荐方案
黑客如何利用漏洞与弱口令入侵网站服务器?
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?
如何在阿里云部署织梦网站?
建站之星如何一键生成手机站?
*请认真填写需求信息,我们会在24小时内与您取得联系。