我使用eclipse来生成对象的hashCode和equals方法的覆盖,并生成了一些关于hashCode覆盖的问题。以下hashCode()是否正确?
问题:
- 为什么eclipse会生成两行 result = 代码行?我认为将两个结果加在一起是合适的。任何想法为什么他们是单独的任务?
- 最终的int prime是否为任何素数?
- int结果总是1?
public class Overrider {
private Long id;
private String name;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
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;
Overrider other = (Overrider) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
答案 0 :(得分:1)
- 为什么eclipse会产生两个结果=代码行?我认为将两个结果加在一起是合适的。任何想法为什么 他们是单独的任务?
请记住,这是在eclipse中运行以生成代码的代码。因此,有一个特定的逻辑。 每个变量生成一行而不是一行生成一行要容易得多。
此外,它使代码更具可读性......您能想象将这两个语句合并为一个吗?
return prime * (prime + ((id == null) ? 0 : id.hashCode()) ) +
((name == null) ? 0 : name.hashCode());
我不打算简化它,但如果有10个类变量,它会变得非常大而且可怕......
“最终的int prime可以是任何素数吗?”
看看:Why does Java's hashCode() in String use 31 as a multiplier? 我引用那里引用了“有效Java”一书......
根据约书亚布洛赫的有效Java(一本不可能的书) 建议不够,我买了,这要归功于不断的提及 计算器):
“选择值31是因为它是一个奇数素数。如果它是偶数 并且乘法溢出,信息将丢失,如 乘以2相当于移位。使用的好处 素数不太清楚,但它是传统的。 31的不错的财产是 乘法可以用移位和减法代替 为了更好的性能:31 * i ==(i <&lt; 5) - i。现代VM执行此操作 自动进行优化。“
答案 1 :(得分:1)
- 为什么eclipse会产生两个结果=代码行?我认为将两个结果加在一起是合适的。任何想法为什么他们是单独的任务? 答案:您已修复上面定义的'final int prime = 31;'。 假设以下情况
id.hashcode()= 1&amp; name.hashcode()= 2。 Hashcode by addition = 32 + 33 = 65 Hashcode with eclipse Implementation = 994
id.hashcode()= 2&amp; name.hashcode()= 1。 Hashcode by addition = 33 + 32 = 65 Hashcode with eclipse Implementation = 1024
Hashcode应尽可能独特,以获得更好的性能。添加结果后,可能有2个不同的对象返回相同的哈希码。而乘法,对不同对象的重复哈希码的可能性非常小。
- 最终的int prime是任何素数吗? 它可以是任何数字,但它确保不同对象的重复哈希码可能性更小。例如,上面表示即使两个不同对象的id.hashcodes中的1的差异将确保这两个对象的实际哈希码在至少31之间不同.S
- int结果总是1? 它可以是任何东西。只是它应该是非零的,并且应该避免计算的复杂性,以使其快速工作。
答案 2 :(得分:1)
对我来说很好。
“为什么eclipse会产生两个结果=代码行?”
我猜的原因是可读性。看起来你再次将第一个结果+第二个字段的哈希乘以素数,而不仅仅是将两个线加在一起。生成的代码看起来好多了:
result = (prime * result + ((id == null) ? 0 : id.hashCode())) +
(prime * (prime * result + ((id == null) ? 0 : id.hashCode())) +
((name == null) ? 0 : name.hashCode()));
是的,但越高越好。数字越大,发生碰撞的可能性越小。在大多数情况下,31应该绰绰有余。“最终的int prime可以是任何素数吗?”
“int int结果总是1?”
假设您的意思是“应该将int结果始终初始化为1”:
不,它只需要一些不为0的常量。