5

经过研究,我仍然找不到针对我的问题的具体解决方案。我有一个使用 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 方法一致的方法。

4

2 回答 2

6

equals自己甚至在你到达之前就违反了合同,hashCode因为它不是传递的。

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

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

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

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

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

于 2017-10-30T13:37:29.010 回答
2

我同意 Kayaman:您的 equals 方法的实现方式,您可以拥有三个 EPoint(pointA、pointB 和 pointC):

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

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

但是,如果您需要“几乎相等”的对象具有相同的哈希码,您可以尝试不同的方法:
将每个 EPoint 映射到网格外的一个 EPoint。例如,如果您的 EPoint 的 lat 和 lon 浮动,您可以将每个 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());
}
于 2017-10-30T13:42:37.057 回答