在我们的应用程序中,我经常看到生成的equals和hashCode方法.我不知道为什么他们被覆盖但是我担心它们是生成的(我认为它们非常相似).以下示例显示了该问题.一个SomeBean instnace被创建,它存在firlsty,然后该集合不包含这个对象.这是因为"a"值和哈希码的变化被改变了.HashSet缓存哈希码wright?因此,之前在Hashset中提出的目标的每次更改都是危险的吗?
private class SomeBean{
private Integer a = 0;
public void setA(Integer a) {
this.a = a;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SomeBean someBean = (SomeBean) o;
if (a != null ? !a.equals(someBean.a) : someBean.a != null) return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + a.hashCode();
return result;
}
}
@Test
public void test() throws Exception {
SomeBean sb = new SomeBean();
Set set = new HashSet<>();
set.add(sb);
sb.hashCode();
System.out.println( set.contains(sb));;
sb.setA(4);
System.out.println(set.contains(sb));;
}
Run Code Online (Sandbox Code Playgroud)
hashCode应该被SomeBean类缓存而且永远不会改变吗?它可能看起来像这样:
@Override
public int hashCode() {
if (_hashCode == 0) {
final int prime = 31;
int result = 1;
result = prime * result + a.hashCode();
return result;
} else return _hashCode;
}
}
Run Code Online (Sandbox Code Playgroud)
但是现在我冒了那个"a"= 0的对象和用"a"= 0创建的每个其他新对象然后改变的对象是相同的对象.
它不会起作用.原因是HashSet基于这样的假设:对象的哈希码不会改变,但是你改变了对象的值:
sb.setA(4);
Run Code Online (Sandbox Code Playgroud)
这会改变哈希码的值.
内部哈希映射基于数组.散列码用于选择数组中用于散列图实现的位置,并且因为散列码从一个调用更改为另一个HashSet正在查看数组中的不同位置.由于数组中的另一个元素是空的,HashSet假定数据结构中不存在这样的元素.
| 归档时间: |
|
| 查看次数: |
51 次 |
| 最近记录: |