You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何HashSet可插入两个相等的Quadruple实例?技术咨询

问题原因分析

这个问题我太熟了——本质是你没重写Quadruple类的equals()和hashCode()方法,导致HashSet没法正确判断两个实例是不是“相同”的元素。

HashSet 判断元素重复的核心逻辑是先比较哈希码是否相等,再用equals方法做最终确认,而你的Quadruple类直接继承了Object类的默认实现:

  • Object.equals():默认比较对象的内存地址,只有两个引用指向同一个对象时才返回true
  • Object.hashCode():默认返回和对象内存地址绑定的数值,哪怕两个实例属性完全一致,只要是不同对象,哈希码大概率不同

所以哪怕两个Quadruple的a/b/c/d属性完全一样,在HashSet眼里它们也是两个独立的对象,自然能被重复插入。

解决方法:重写equals()和hashCode()

要让HashSet正确识别属性相同的Quadruple实例,你必须手动重写这两个方法,并且严格遵守equals相等的对象,hashCode必须相等的约定。

因为你的histogram是由a/b/c/d派生出来的,所以只需要基于这四个int属性实现即可(如果要包含histogram,注意HashMap.equals()会比较所有键值对,这里因为histogram由四个属性生成,结果和用a/b/c/d判断是一致的)。

示例代码:

public static class Quadruple {
    int a;
    int b;
    int c;
    int d;
    Map<Integer, Integer> histogram;

    public Quadruple(int a, int b, int c, int d) {
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
        this.histogram = new HashMap<>();
        // 简化histogram初始化逻辑
        histogram.put(a, histogram.getOrDefault(a, 0) + 1);
        histogram.put(b, histogram.getOrDefault(b, 0) + 1);
        histogram.put(c, histogram.getOrDefault(c, 0) + 1);
        histogram.put(d, histogram.getOrDefault(d, 0) + 1);
    }

    // 重写equals方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Quadruple quadruple = (Quadruple) o;
        return a == quadruple.a && b == quadruple.b && c == quadruple.c && d == quadruple.d;
    }

    // 重写hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(a, b, c, d);
    }
}
补充提醒
  • 千万不要只重写其中一个方法:如果只重写equals()不重写hashCode(),会导致两个equals相等的对象哈希码不同,HashSet会把它们放到不同的桶里,永远不会触发equals比较,还是会被当成不同元素插入。
  • 可以直接用IDE的自动生成功能(比如IntelliJ的Alt+Insert)来生成这两个方法,避免手动编写出错。

内容的提问来源于stack exchange,提问作者Alek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:06:17