java中用hashset去重需重写hashcode和equals,否则自定义对象无法正确识别重复;保序应选linkedhashset;流式处理可用add()返回值自动过滤。

Java 中用 HashSet 过滤重复的业务数据,核心在于让业务对象能被正确识别为“重复”——这不取决于对象地址,而取决于你定义的业务逻辑是否相等。直接 new HashSet(list) 只对字符串、数字等基础类型或已重写 hashCode 和 equals 的类有效;若用自定义对象(如 User、Order),不重写这两个方法,HashSet 会把每个 new 出来的实例都当作不同元素,去重完全失效。
确保业务语义去重:必须重写 hashCode 和 equals
比如一个订单类,业务上认为 orderId 相同就是同一笔订单:
- 不重写:两个 new Order("ORD-001", ...) 会被视为不同对象,HashSet 保留两份
- 重写后:只要 orderId 相同,无论创建几次,HashSet 只存一份
推荐用 IDE 自动生成,或使用 Objects.hash(id) 和 Objects.equals(this.id, other.id),避免 null 判空异常。
基础去重操作:一行构造 + 自动过滤
适用于 List 转 Set 场景,不关心顺序:
- Set
uniqueNames = new HashSet(originalList); -
Set
uniqueOrders = new HashSet(orderList); (前提是 Order 已重写 hashCode/equals)
注意:结果顺序不确定,不能用于需要保持首次出现顺序的场景。
要保序?换 LinkedHashSet
如果原始列表中第一次出现的顺序很重要(例如日志解析、接口响应保序),就别用 HashSet:
- Set
orderedUnique = new LinkedHashSet(originalList); - 它底层用链表维护插入顺序,add 时跳过重复项,遍历时严格按首次添加顺序输出
- 性能略低于 HashSet,但单线程下几乎无感知,是业务去重最稳妥的选择
流式处理:边读边滤,用 add() 返回值判断
适合循环处理数据库游标、文件逐行读取、网络响应流等场景:
- LinkedHashSet
seenIds = new LinkedHashSet(); - for (Long id : idStream) { seenIds.add(id); }
- add() 返回 true 表示新增成功(此前未见过),false 表示跳过重复
- 无需手动 contains(),查重和保序一步到位,代码简洁且不易出错
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











