我在Windows XP上的Hotspot JDK 1.6中运行下面的代码,我运行了两次,我得到了下面的结果.
所以基本上似乎object.hashcode()也有冲突?看起来它没有返回VM中的内存地址.
但是,JDK中的一条评论说价值观应该是截然不同的,任何人都可以解释一下吗?
尽可能合理,Object类定义的hashCode方法确实为不同的对象返回不同的整数.(这通常通过将对象的内部地址转换为整数来实现,但Java TM编程语言不需要此实现技术.)
Run Code Online (Sandbox Code Playgroud)@return a hash code value for this object. @see java.lang.Object#equals(java.lang.Object) @see java.util.Hashtable
这是第一个结果:
i,hashcode(): 361,9578500
i,hashcode(): 1886,9578500
conflict:1886, 361
i,hashcode(): 1905,14850080
i,hashcode(): 2185,14850080
conflict:2185, 1905
9998
Run Code Online (Sandbox Code Playgroud)
这是第二个结果:
i,hashcode(): 361,5462872
i,hashcode(): 1886,29705835
conflict:1887, 362
i,hashcode(): 1905,9949222
i,hashcode(): 2185,2081190
conflict:2186, 1906
9998
10000
Run Code Online (Sandbox Code Playgroud)
我的代码:
@Test
public void testAddr()
{
Set<Integer> s = new TreeSet<Integer>();
Map<Integer, Integer> m = new TreeMap<Integer, Integer>();
Set<Object> os = new HashSet<Object>();
for(int i = 0; i < 10000; ++i)
{
Object o = new Object();
os.add(o);
Integer h = o.hashCode();
if((i == 361) || (i == 1886) || (i == 2185) || (i == 1905))
{
System.out.println("i,hashcode(): " + i + "," + h);
}
if(s.contains(h))
{
System.out.println("conflict:" + i + ", " + m.get(h));
}
else
{
s.add(h);
m.put(h, i);
}
}
System.out.println(s.size());
int c = 0;
for(Object o: os)
{
c++;
}
System.out.println(c);
}
Run Code Online (Sandbox Code Playgroud)
hashCode()应该用于在哈希表中放置对象.该规则hashCode是不是认为hashCode不应该产生冲突,尽管这是一个理想的财产,但相等的对象必须具有相同的散列码.这并不排除不相等的对象具有相同的哈希码.
您已经找到了一种情况,默认Object.hashCode()实现确实为不相等的对象生成相同的哈希码.除非该对象与另一个对象的某些字段感情相等,否则要求对象的哈希码不会改变.一个可能的原因是垃圾收集器重新安排了内存,以便稍后实例化与o早期实例化在同一位置o(即,您o在循环中分配了两个对象,并且垃圾收集器在两个分配之间重新安排了内存,因此旧的o移出一个内存位置,o然后在那个位置分配新的).然后,即使旧的哈希码o不能改变,新的哈希码o也是新o存储在内存中的地址,这恰好等于旧的哈希码o.