Eclipse源菜单有一个“generate hashCode/equals method”,它生成如下函数。
String name;
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CompanyRole other = (CompanyRole) obj;
if (name == null)
{
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
如果我在生成hashCode()
和equals()
时选择多个字段,Eclipse使用上面显示的相同模式。
我不是散列函数的专家,我想知道生成的散列函数有多“好”?在什么情况下它会发生故障并导致太多碰撞?
您可以看到< code>java.util.ArrayList中hashCode函数的实现如下
public int hashCode() {
int hashCode = 1;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
}
return hashCode;
}
这是一个这样的例子,你的Eclipse生成的代码遵循类似的实现方式。但是如果你觉得你必须自己实现你的hashCode,约书亚·布洛赫在他著名的《有效Java》一书中给出了一些很好的指导方针。我将从那本书的第9项中发布那些要点。那些是,
>
对于对象中的每个有效字段f(equals方法考虑的每个字段),执行以下操作:
一个。计算字段的整型哈希代码 c:
I .如果字段是布尔值,则计算(f?1 : 0).
ii.如果字段是字节、字符、短或整数,则计算(整数)f。
iii.如果字段很长,则计算(int)(f^(f
四。如果字段是浮点数,则计算float . float pointbits(f)。
五.如果字段是双精度的,计算Double.doubleToLongBits(f),然后哈希得到的long,如步骤2.a.iii.
vi. 如果字段是对象引用,并且此类的 equals 方法通过递归调用等于来比较字段,则递归地调用字段上的哈希代码。如果需要更复杂的比较,请计算此字段的“规范表示形式”,并在规范表示形式上调用 hashCode。如果字段的值为 null,则返回 0(或其他一些常量,但 0 是传统值)
七。如果该字段是一个数组,则将其视为每个元素都是一个单独的字段。也就是说,通过递归应用这些规则来计算每个重要元素的哈希代码,并按照步骤2.b组合这些值。如果数组字段中的每个元素都是重要的,则可以使用1.5版中添加的Arrays.hashCode方法之一。
b、 将步骤2.a中计算的哈希代码c合并为以下结果:
result = 31 * result + c;
返回结果。
编写完hashCode方法后,问问自己相等的实例是否具有相等的哈希代码。编写单元测试来验证您的直觉!如果相等的实例具有不相等的哈希代码,请找出原因并解决问题。
我想Java语言设计者和Eclipse似乎遵循相似的指导方针。快乐编码。干杯。
由于Java 7,您可以使用Java.util。对象
编写简洁优雅的方法:
class Foo {
private String name;
private String id;
@Override
public int hashCode() {
return Objects.hash(name,id);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Foo) {
Foo right = (Foo) obj;
return Objects.equals(name,right.name) && Objects.equals(id,right.id);
}
return false;
}
}
一般来说是好的,但是: