Axe*_*xel 20 java enums hashmap hashcode
我有一个包含不同枚举(不同类型)的类.该类用作a的键HashMap.hashCode类目前实现如下:
public static class Key implements Comparable<Key> {
final int a;
final Enum1 enum1;
final Enum2 enum2;
@Override
public int hashCode() {
return a ^ enum1.hashCode() ^ enum2.hashCode();
}
// ... definition of equals and toString ...
}
Run Code Online (Sandbox Code Playgroud)
现在,如果枚举hashCode只返回枚举定义中枚举值的索引,这将不是最佳的(太多冲突).方法定义Enum.hashCode()是这样的:
/**
* Returns a hash code for this enum constant.
*
* @return a hash code for this enum constant.
*/
public final int hashCode() {
return super.hashCode();
}
Run Code Online (Sandbox Code Playgroud)
假设这个委托Object.hashCode(),一切都应该没问题,因为每个枚举常量只存在一个实例,Object.hashCode()理论上就是从对象的内部地址派生的整数.我对吗?
PS:当在键中多次使用相同的枚举时,你将不得不使用更复杂的东西.
Miq*_*uel 15
是的,你是对的,因为枚举元素的哈希码将来自静态实例,绑定到内存位置,并且是唯一的.
另一方面,有更好的方法来生成具有较少冲突概率的哈希码.例如,查看eclipse可以为您自动生成的默认值(右键单击,Source> Generate hashCode and equals)
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((enum1 == null) ? 0 : enum1.hashCode());
result = prime * result + ((enum2 == null) ? 0 : enum2.hashCode());
return result;
}
Run Code Online (Sandbox Code Playgroud)
通过将素数投入混合(精确的数学逃避我),你应该更有抵抗力.
注意你也可以让eclipse为你生成一个equals方法!(甚至是toString).不是说你必须盲目相信他们,但他们通常是一个非常好的开始.
小智 6
如上所述,Enum 在 Java 中是不可变的,因此为 Enum 生成的哈希码是 Hash 集合的完美键,就像 String 是完美键一样。
枚举声明是一种特殊的类声明。枚举类型对于每个命名枚举常量都有公共的自类型成员。所有枚举类都具有高质量的 toString、hashCode 和 equals 方法。所有这些都是可序列化的、可比较的并且实际上是最终的。没有一个是可克隆的。除了 toString 之外的所有“对象方法”都是最终的:我们负责比较和序列化,并确保它正确完成。