Stream按对象某属性去重的方案
·
1.Collectors.collectingAndThen
- 这是Stream中的一个收集器,相比普通的Collectors.toList、Collectors.groupingBy等收集器
- Collectors.collectingAndThen还可以在收集之后进行某种操作
- 多一个形参,用于写function函数(有入参有出参)
举例说明collectingAndThen:
List按某属性去重,返回List
2.本质流程
使用Collectors.collectingAndThen的本质是:先把new Set( list ) 获取一个Set,然后new List ( set )返回List
3. 如何用Set去重
用TreeSet和HashSet都能去重,只是去重的逻辑不一样。先看二者的存储逻辑:
- Hashset是通过复写hashCode()方法和equals()方法来保证的。
- 而Treeset是通过Compareable接口的compareto方法来保证的。同理可以用Comparator来定制排序
3.1TreeSet去重
①自然排序Comparable接口
@Data
public class DtoReq implements Comparable {
private String userName;
private String password;
@Override
public int compareTo(Object o) {
DtoReq req = (DtoReq)o;
return req.getUserName().compareTo(this.getUserName());
}
}
- 代码逻辑即:对userName字段进行比较,且TreeSet的去重功能不需要关注顺序,谁比谁都一样
- 不过这种方式相当于写死了,耦合度太高
去重代码
ArrayList<DtoReq> collect = arrayList.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
TreeSet::new),ArrayList::new)
);
new TreeSet(arrayList)时构造器会自动去比较Comparable
接口的compareTo
方法,而达到去重的效果
②定制排序Comparator接口
-
当元素的类型没实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序
-
应该用匿名对象重写
compare
方法 或用lambda表达式调用Comparator.comparing
方法@Data
public class DtoReq {private String userName;
private String password;}
匿名对象重写compare方法
/**
* 定制排序Comparator对象,封装了排序的逻辑
* 这里的泛型千万不能省,会用作lambda表达式的类型推断
*/
Comparator<DtoReq> comparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
DtoReq r1 = (DtoReq)o1;
DtoReq r2 = (DtoReq)o2;
return r1.getUserName().compareTo(r2.getUserName());
}
};
ArrayList<DtoReq> collect = arrayList.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(comparator)
)
, ArrayList::new)
);
静态方法comparing+lambda表达式
不需要new那个Comparator对象并重写其compare方法,直接调用静态方法Comparator.comparing
方法,其形参是方法引用
,意为:针对某属性进行排序,当然这里不是为了排序,只是为了去重
ArrayList<DtoReq> collect = arrayList.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(DtoReq::getUserName))
)
, ArrayList::new)
);
3.2HashSet去重
- 利用HashSet去重,只需要重写其
equals()
和hashCode()
方法 - 而好巧不巧lombok的@data注解提供了这两个方法的重写
lombok引入@data
@Data
public class DtoReq {
private String userName;
private String password;
}
此时就已经有了equals()和hashCode()方法,直接用就好
直接调HashSet构造器
ArrayList<DtoReq> collect = arrayList.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new HashSet<>()
)
, ArrayList::new)
);
方法引用进行优化
ArrayList<DtoReq> collect = arrayList.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
HashSet::new) , ArrayList::new)
);
4.去重逻辑
5.为什么不用distinct()
Stream流有一个distinct()方法可以去重,但是这个distinct()是直接调用当前流中存储对象的equals()方法,而Set会计算哈希值
List去重以及效率分析
推荐内容
阅读全文
AI总结
更多推荐
相关推荐
查看更多
FramePack

高效压缩打包视频帧的工具,优化存储与传输效率
public-apis

这个项目收集了大量公开可用的API接口,适合开发者查找和利用各类公开API来快速构建应用程序或获取所需数据,覆盖范围广泛,从社交、新闻到天气、地图等各种领域。
n8n

n8n 是一个工作流自动化平台,它结合了代码的灵活性和无代码的高效性。支持 400+ 集成、原生 AI 功能以及公平开源许可,n8n 能让你在完全掌控数据和部署的前提下,构建强大的自动化流程。源项目地址:https://github.com/n8n-io/n8n
热门开源项目
活动日历
查看更多
直播时间 2025-04-09 14:34:18

樱花限定季|G-Star校园行&华中师范大学专场
直播时间 2025-04-07 14:51:20

樱花限定季|G-Star校园行&华中农业大学专场
直播时间 2025-03-26 14:30:09

开源工业物联实战!
直播时间 2025-03-25 14:30:17

Heygem.ai数字人超4000颗星火燎原!
直播时间 2025-03-13 18:32:35

全栈自研企业级AI平台:Java核心技术×私有化部署实战
目录
所有评论(0)