我们如何决定集合的hashCode()方法的最佳实现(假设equals方法已被正确重写)?


当前回答

如果你使用eclipse,你可以使用以下方法生成equals()和hashCode():

生成hashCode()和equals()。

使用此函数,您可以决定使用哪些字段进行相等和散列代码计算,Eclipse将生成相应的方法。

其他回答

这里有一个非常严重的bug。

Zam obj1 = new Zam("foo", "bar", "baz");
Zam obj2 = new Zam("fo", "obar", "baz");

同样的hashcode

你可能想要

public int hashCode() {
    return (getFoo().hashCode() + getBar().hashCode()).toString().hashCode();

(现在你能在Java中直接从int获取hashCode吗?我认为它做了一些自动铸造。如果是这种情况,跳过toString,它很难看。)

只是一个快速的注释,以完成其他更详细的答案(在代码方面):

如果我考虑如何在java中创建哈希表的问题,特别是jGuru FAQ条目,我相信可以判断哈希代码的其他标准是:

同步(算法是否支持并发访问)? 失败安全迭代(算法是否检测到迭代过程中发生变化的集合) 空值(哈希码是否支持集合中的空值)

最好的实现?这是一个很难回答的问题,因为这取决于使用模式。

Josh Bloch的Effective Java在第8项(第二版)中提出了几乎所有情况下合理的良好实现。最好的办法是去查一下,因为作者在那里解释了为什么这种方法是好的。

简短的版本

Create a int result and assign a non-zero value. For every field f tested in the equals() method, calculate a hash code c by: If the field f is a boolean: calculate (f ? 0 : 1); If the field f is a byte, char, short or int: calculate (int)f; If the field f is a long: calculate (int)(f ^ (f >>> 32)); If the field f is a float: calculate Float.floatToIntBits(f); If the field f is a double: calculate Double.doubleToLongBits(f) and handle the return value like every long value; If the field f is an object: Use the result of the hashCode() method or 0 if f == null; If the field f is an array: see every field as separate element and calculate the hash value in a recursive fashion and combine the values as described next. Combine the hash value c with result: result = 37 * result + c Return result

这将导致在大多数使用情况下哈希值的适当分布。

在Apache Commons Lang中,有效Java的hashcode()和equals()逻辑有一个很好的实现。签出HashCodeBuilder和EqualsBuilder。

我在arrays . deephashcode(…)周围使用了一个小包装器,因为它可以正确地处理作为参数提供的数组

public static int hash(final Object... objects) {
    return Arrays.deepHashCode(objects);
}