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

如何在值处于±10范围内时正确实现equals()与hashCode()方法

问题分析与解决方案

首先要明确:Java中equals()方法必须遵守等价关系契约(自反、对称、传递、一致),你当前的equals()实现违反了传递性,这会导致HashMap、HashSet等哈希集合出现异常行为。比如:

  • 实例a的value=5,实例b的value=15,实例c的value=25
  • a.equals(b)返回true,b.equals(c)返回true,但a.equals(c)返回false
    这种情况不符合等价关系,会让集合无法正确判断元素是否重复。

方案1:修正equals()使其符合契约,再实现hashCode()

如果要让equals()合法,应该将value划分成大小为10的区间,只有落在同一区间的两个值才判定相等(保证传递性)。

修正后的完整代码

public class Test 
{
    private double value;

    // 补充构造方法以便实例化对象
    public Test(double value) {
        this.value = value;
    }

    private boolean isEqualValues(final double valueOne, final double valueTwo)
    {
        // 将值划分到[10n, 10(n+1))的区间,同一区间则判定相等
        long bucketOne = (long) Math.floor(valueOne / 10.0);
        long bucketTwo = (long) Math.floor(valueTwo / 10.0);
        return bucketOne == bucketTwo;
    }

    @Override
    public boolean equals(final Object o)
    {
        if (this == o)
        {
            return true;
        }
        if (o == null || getClass() != o.getClass())
        {
            return false;
        }

        Test test = (Test) o;

        return isEqualValues(test.value, value);
    }

    @Override
    public int hashCode()
    {
        // 基于区间索引生成hashCode,同一区间的对象hashCode必然相同
        long bucket = (long) Math.floor(value / 10.0);
        return Long.hashCode(bucket);
    }
}

方案2:坚持原有equals()逻辑(不推荐)

如果你一定要保留当前“差值±10即相等”的判断(即使违反契约),那唯一能满足equals()相等则hashCode()相同的方式是让所有对象返回同一个固定hashCode:

@Override
public int hashCode() {
    return 42; // 任意固定整数均可
}

但这种做法会让哈希集合的性能暴跌——所有元素都会被放入同一个哈希桶,查询、插入操作的时间复杂度从O(1)退化为O(n),仅适合极端场景。

另外,原代码中的isEqualValues()方法缺少闭合的},已在方案1的代码中修正。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 11:10:52