JavaStream集合中对象单属性去重和多属性去重

更新时间:2023-07-11 19:58:09 阅读: 评论:0

JavaStream集合中对象单属性去重和多属性去重
前⾔:
在Stream中distinct()可以进⾏去重,内部原理是通过构建⼀个ConcurrentHashMap并使⽤putIfAbnt()来去重
但是由于ConcurrentHashMap与HashMap⼀样是通过hashCode()和equals()⽅法来查找和⽐对的⽽如果对象所属的类没有将hashCode()和equals()重写的话就会导致同⼀个类的多个new出来的对象是⽆法判定为"相等"的哪怕属性⼀模⼀样(String相等是因为重写了hashCode()和equals())
因为distinct()只⽀持基本类型,基本类型的封装类型,已重写hashCode()和equals()的类的对象去重,⽆法将⼀个未重写
hashCode()和equals()的普通类进⾏去重所以有了以下解决⽅案
实践代码:
圣诞儿歌
/**
* ⽤于对象去重
* @param keyExtractor 需要去重的属性
* @param <T>
* @return
*/
private static<T> Predicate<T>distinctByKey(Function<?super T,?> keyExtractor){
//记录已有对象或者属性
手腕疼是怎么回事ConcurrentSkipListMap<Object,Boolean> skipListMap =new ConcurrentSkipListMap<>();
//获取对象的属性值,且使⽤putIfAbnt判断存在则不添加到map⽽且返回数值不存在则添加返回null,value恒定为true
//JSONString(keyExtractor.apply(t)) 是为了解决null参数和对象⽐较的问题
//在Stream distinct()中使⽤了⽀持null为key的hashSet来进⾏处理 java/util/stream/DistinctOps.java:90  但是没有解决对象⽐较的问题
平常生活
外盘//所以虽然序列化消耗性能但是也没有更好的办法
Predicate<T> predicate = t -> skipListMap.JSONString(keyExtractor.apply(t)), Boolean.TRUE)== null;
return predicate;
}
药的成语private static class Test {
Integer aid;
Integer uid;
public Test(Integer aid,Integer uid){
this.aid = aid;
this.uid = uid;
}
public Integer getAid(){
return aid;
}
public Test tAid(Integer aid){
this.aid = aid;
return this;
}
public Integer getUid(){
return uid;
}
public Test tUid(Integer uid){
this.uid = uid;
return this;
}
}
public static void main(String[] args){
//待去重列表
List<Test> collect = Stream.of(new Test(2,1),new Test(2,1),new Test(2,2),new Test(1,1),new Test(1,1),new Test(1,2)).List( ));
//filter单属性去重
System.out.JSONString(collect.stream().filter(distinctByKey(Test::getAid)).List())));
//filter多属性去重
用强
System.out.JSONString(collect.stream().filter(distinctByKey(test -> Stream.Aid(),Uid()).toArray())).collect(List())));
//collectingAndThen 单属性去重,会打乱collect原有排序变成⾃然升序
System.out.JSONString(collect.stream().Collection(()->new ConcurrentSkipList Set<>(paring(Test::getAid))),ArrayList::new))));
//collectingAndThen 多属性去重,会打乱collect原有排序变成⾃然升序
System.out.JSONString(collect.stream().Collection(()->new ConcurrentSkipList Set<>(paring(Test::getAid).thenComparing(Test::getUid))),ArrayList::new))));
}
热门手机运⾏结果:
[{"aid":2,"uid":1},{"aid":1,"uid":1}]
[{"aid":2,"uid":1},{"aid":2,"uid":2},{"aid":1,"uid":1},{"aid":1,"uid":2}]
[{"aid":1,"uid":1},{"aid":2,"uid":1}]
[{"aid":1,"uid":1},{"aid":1,"uid":2},{"aid":2,"uid":1},{"aid":2,"uid":2}]
总结:
filter需要额外的distinctByKey()⽅法还有序列化的性能消耗,但是不会打乱数据原有顺序collectingAndThen ⽐较简单快捷性能也是ok的,但是会打乱数据原有顺序变成⾃然顺序⼆者如何取舍请从实际情况出发
>何厌之有

本文发布于:2023-07-11 19:58:09,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1077458.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:对象   属性   类型   打乱
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图