论坛首页 Java企业应用论坛

HashMap存储结构浅析

浏览 23668 次
精华帖 (0) :: 良好帖 (12) :: 新手帖 (1) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-12-11  
yangyi 写道
...
length是基于power of 2的,所以length - 1的binary形式一定是一堆1,然后做与运算的结果就是取优化后哈希值的低位

原来如此,受教了
还有一点疑问,与运算会将计算出的哈希值转换成正的吧?上面有提到过溢出的问题,这样可能会导致二进制符号位为1,得出的值是负数,而进行与运算后会重新把哈希值的符号位变成0。是这样理解的么?
0 请登录后投票
   发表时间:2010-12-11  
pengmj 写道
什么是hashcode
    ....

这里需要提一下Object规范里规定:如果两个对象根据equals(Object)方式是相等的,那么这两个对象的hashCode一定要相等。



我查了一下API,Object里面的equals函数的说明以下:

指示其他某个对象是否与此对象“相等”。
equals 方法在非空对象引用上实现相等关系:

自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null) 都应返回 false。
Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。

注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
--------end-------


当equals==true时,个人认为hashcode可以不相同,但是在set中,是否判断为同一个对象不仅仅是通过equals方法,还要hashcode相同时,才判断为同一个对象。
0 请登录后投票
   发表时间:2010-12-11  
这是不可能的,你看一下HashMap的代码实现,里面的MAX_CAPACITY是Integer Max Value的一半,也就是低位的部分不可能出现在符号位上
0 请登录后投票
   发表时间:2010-12-11  
数据结构一书有学过
0 请登录后投票
   发表时间:2010-12-11  
RonQi 写道
楼主好文呢,这一个“浅析”让很多非计算机专业的同学补充了数据结构方面的知识,功德无量,
一个笔误
引用
基本结构它包含三个类,key,value和指向下一个Entity的next

楼主是说包含三个属性吧

还有些困惑一个小问题
引用

比如一个字符串“abc”(a的ascii码是97),它的hashcode算法是:
h = 31 * 0 + 97 ==> h = 97;
h = 31 * 97 + 98 ==> h = 3105;
h = 31 * 3105 + 99 ==> h = 96354;
所以“abc”的hashCode就是96354

如果照这个方法算下去,对于稍长的字符串hashCode岂不是越来越大?很快int就放不下来了吧?

哈哈,你的问题很好。
不管它如何增大,它只取32位,所以说会出现负数。
hashcode的范围就是一个int的范围-2^32到2^31
0 请登录后投票
   发表时间:2010-12-11  
worldterminator 写道
能讲讲怎么扩展hash表么, length增加了,根据 %length 计算 索引不到啊

你的意思是不是“如果HashTable中的数组的length自动扩展了,它里面已经存在的Entity如何索引是吗?”
HashTable里面有一个方法叫rehash(),它就是在length扩展的时候调用的,它的目的就是为里面已有的元素重新计算索引。
HashMap也类似,不过方法名叫resize()。
下面是HashTable中的rehash()
protected void rehash() {
	int oldCapacity = table.length;
	Entry[] oldMap = table;

	int newCapacity = oldCapacity * 2 + 1;
	Entry[] newMap = new Entry[newCapacity];

	modCount++;
	threshold = (int)(newCapacity * loadFactor);
	table = newMap;

	for (int i = oldCapacity ; i-- > 0 ;) {
	    for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
		Entry<K,V> e = old;
		old = old.next;

		int index = (e.hash & 0x7FFFFFFF) % newCapacity;
		e.next = newMap[index];
		newMap[index] = e;
	    }
	}
    }

threshold 是一个门槛,这个值是容量和加载因子的乘积,只要HashTable的size大于或等于threshold,那么这个容器就要进行扩展了。
0 请登录后投票
   发表时间:2010-12-12  
Entry里面的key是什么?
0 请登录后投票
   发表时间:2010-12-12  
liuzhiqiangruc 写道
Entry里面的key是什么?

Entry里面的key就是HashMap.put(k,v)中的“k”
0 请登录后投票
   发表时间:2010-12-12  
xieboxin 写道
pengmj 写道
什么是hashcode
    ....

这里需要提一下Object规范里规定:如果两个对象根据equals(Object)方式是相等的,那么这两个对象的hashCode一定要相等。



我查了一下API,Object里面的equals函数的说明以下:

指示其他某个对象是否与此对象“相等”。
equals 方法在非空对象引用上实现相等关系:

自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null) 都应返回 false。
Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。

注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
--------end-------


当equals==true时,个人认为hashcode可以不相同,但是在set中,是否判断为同一个对象不仅仅是通过equals方法,还要hashcode相同时,才判断为同一个对象。


把EFFECTIVE JAVA 的东西都搬出来了,回复也是如此COPY
0 请登录后投票
   发表时间:2010-12-12  
以前看过,后来忘记了。
不过今天看这些讨论,又有新的收获,那就是hashmap的初始数组长度为什么是16.
受教了,另外增长为什么是倍数增长,原来都是有原因的啊。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics