7

我有一个以坐标为键的 HashMap。

坐标有 3 个长整数,分别保存 x、y 和 z 坐标。(坐标是并且需要是自定义类,坐标需要是长整数)。

现在我希望能够通过执行以下操作访问例如字段 [5, 10, 4] hashMap.get(new Coordinate(5, 10, 4)):。

我已经实现了 equals 方法,但这还不够,因为显然我还需要为 hashCode 提供一个实现。所以我的问题是如何从三个 long 中生成唯一的 hashCode?.

附加:使用来自外部库的哈希生成器不是选项。

4

5 回答 5

17

Joshua Bloch 在他的“Effective Java”的第 3 章中告诉您如何为 Coordinate 类编写 equals 和 hashCode 。

像这样:

public class Coordinate
{
    private long x;
    private long y;
    private long z;

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

        Coordinate that = (Coordinate) o;

        if (x != that.x) return false;
        if (y != that.y) return false;
        if (z != that.z) return false;

        return true;
    }

    @Override
    public int hashCode()
    {
        int result = (int) (x ^ (x >>> 32));
        result = 31 * result + (int) (y ^ (y >>> 32));
        result = 31 * result + (int) (z ^ (z >>> 32));
        return result;
    }
}
于 2011-04-20T12:25:36.260 回答
5

这是一个老问题,但如果有人碰到它,现在有一种更简单的方法:

@Override 
public int hashCode() {
    return Objects.hash(x, y, z);
}
于 2019-10-28T12:36:07.003 回答
4

在 Java 中,标准hashCode()方法返回int32 位。

long数据类型为 64 位。因此,三个longs 表示 192 位信息,当然不能被任何散列函数唯一地映射成 32 位的散列值。

但是,aHashMap不需要唯一的哈希,它会在发生冲突时简单地处理冲突。

一种天真的方法是构建字符串,即“x,y,z”,然后对字符串进行哈希处理。

您也可以尝试将这些值组合在一起:

int hashCode()
{
  return (int) (x ^ y ^ z);
}
于 2011-04-20T12:25:40.010 回答
2

如何从三个 long 中生成唯一的 hashCode?

你不需要。哈希码不需要是唯一的。

于 2011-04-20T12:26:56.907 回答
1

您应该意识到哈希码和要在 HashMap 中使用的唯一键之间存在差异。

您的 Coordinate 类的哈希码根本不必是唯一的......

哈希码的一个好的解决方案是:

(int)(x ^ (x >> 32) ^ y ^ (y >> 32) ^ z ^ (z >> 32));

Wich 是每个 longs XOR 的两半的 XOR 在一起。

于 2011-04-20T12:32:42.317 回答