不一致的哈希码,等于Java



经过研究,我仍然找不到我的问题的具体解决方案。我有一个使用 epsilon 的"近似等于"方法,而我的 hashCode 方法使用确切的值。当我比较值时,这打破了 HashSet 的先决条件。

@Override
public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof EPoint)) {
        return false;
    }
    EPoint ePoint = (EPoint) o;
    return Math.abs(Math.abs(ePoint.lat) - Math.abs(lat)) < EPSILON && Math.abs(Math.abs(ePoint.lon) - Math.abs(lon)) < EPSILON;
}
@Override
public int hashCode() {
    return Objects.hash(lat, lon);
}

我找不到一种方法使 hasCode() 与我的 equals 方法保持一致。

你的equals本身甚至在你进入hashCode之前就破坏了契约,因为它不是可传递的。

这也立即导致唯一一致的hashCode实现是返回一个常量,因为对于任何两个点,都有一个(很长的)中间点链,因此

  1. 每两个邻居相等,因此

  2. 每两个邻居必须具有相同的hashCode,因此

  3. 开头和结尾必须具有相同的hashCode

现在,这是一个一致的实现,但显然是一个无用的实现。

我同意 Kayaman 的观点:您的 equals methos 的实现方式,您可以有三个 EPoint(点 A、点 B 和点 C):

pointA.equals(pointB) //true
pointA.equals(pointC) //true
pointB.equals(pointC) //false

这是不允许的。创建具有其他名称的方法可能是一种解决方案。

但是,如果您需要"几乎相等"的对象具有相同的哈希代码,则可以尝试不同的方法:
将每个 EPoint 映射到网格外的 EPoint。例如,如果您的 EPoint 的纬度和纬度浮动,您可以将每个 EPoint 映射到具有四舍五入的 int 值的 EPoint。
如果你需要更高的精度,你可以扩展它并进入第一,第二,...小数位)。

如果你对"映射"点执行 equals() 和 hashcode() 方法,这应该满足所有要求:

@Override
public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof EPoint)) {
        return false;
    }
    EPoint ePoint = (EPoint) o;
    return this.gridLon() == ePoint.gridLon() && ePoint.gridLat() == this.gridLat();
}
@Override
public int hashCode() {
    return Objects.hash(this.gridLon(), this.gridLat());
}

相关内容

  • 没有找到相关文章

最新更新