hashset多条件去重关键在于equals()和hashcode()必须一致使用相同字段参与计算,如订单按用户id、商品id、下单日期联合判等,二者均需包含且仅包含这些字段,并确保null安全与字段不可变。

HashSet 实现多条件联合对象的唯一性去重,关键不在 HashSet 本身,而在于你如何定义“相同”——也就是让多个字段共同参与 equals() 和 hashCode() 的计算逻辑。
核心原则:所有用于判等的字段,必须同时参与 equals 和 hashCode
比如一个订单对象 Order,你想按 用户ID + 商品ID + 下单日期 三者联合判定是否重复。那么:
- equals() 必须比较这三个字段是否全部相等(且都非 null,或按需处理 null)
- hashCode() 必须用这三个字段一起计算哈希值,不能只用其中一两个
- 如果漏掉某个字段,比如 hashCode 里没用下单日期,那两个“同用户同商品但不同日期”的订单可能被算出相同哈希值 → 进同一桶 → equals 又不比日期 → 误判为重复
- 如果 equals 比了三个字段,但 hashCode 只用了用户ID,那它们大概率进不同桶 → equals 根本不会被调用 → 明明该去重却留了两个
自定义类必须重写这两个方法(不能依赖默认实现)
Object 默认的 hashCode 基于内存地址,equals 基于引用,对多条件毫无意义。正确做法是:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 手动编写:确保字段选取一致、null 安全(如用 Objects.equals(a, b) 和 Objects.hash(f1, f2, f3))
- 用 IDE 生成(IntelliJ / Eclipse):勾选全部参与联合判等的字段
- 用 Lombok:加 @EqualsAndHashCode(include = {"userId", "productId", "orderDate"}),显式指定字段,避免漏掉或误含
字段选择要稳定,别用会变的值
参与判等的字段一旦加入 Set,后续就不该修改。例如:
- 如果把 订单状态 也加进 equals,但之后调 order.setStatus("shipped"),这个对象在 HashSet 中就再也找不到了(因为哈希值变了,桶位置失效)
- 联合去重通常只用业务主键类字段:ID、编码、时间戳、类型码等不可变或极少变的标识性字段
- 若字段确实可能变化,应先从 Set 中 remove,再修改,再 add;或者改用其他结构(如 Map
自定义 Key)
验证是否生效:简单两步测试
写个最小用例,确认逻辑可靠:
- 创建两个字段值完全相同的对象,add 进 HashSet,size 应为 1
- 打印它们的 hashCode(),必须相等;调用 equals(),必须返回 true
- 故意改其中一个字段(如只改备注),hashCode 应不同,equals 应返回 false










