锁定老帖子 主题:HashMap存储结构浅析
精华帖 (0) :: 良好帖 (12) :: 新手帖 (1) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-12-11
yangyi 写道 ...
length是基于power of 2的,所以length - 1的binary形式一定是一堆1,然后做与运算的结果就是取优化后哈希值的低位 原来如此,受教了 还有一点疑问,与运算会将计算出的哈希值转换成正的吧?上面有提到过溢出的问题,这样可能会导致二进制符号位为1,得出的值是负数,而进行与运算后会重新把哈希值的符号位变成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相同时,才判断为同一个对象。 |
|
返回顶楼 | |
发表时间:2010-12-11
这是不可能的,你看一下HashMap的代码实现,里面的MAX_CAPACITY是Integer Max Value的一半,也就是低位的部分不可能出现在符号位上
|
|
返回顶楼 | |
发表时间:2010-12-11
数据结构一书有学过
|
|
返回顶楼 | |
发表时间: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 |
|
返回顶楼 | |
发表时间: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,那么这个容器就要进行扩展了。 |
|
返回顶楼 | |
发表时间:2010-12-12
Entry里面的key是什么?
|
|
返回顶楼 | |
发表时间:2010-12-12
liuzhiqiangruc 写道 Entry里面的key是什么?
Entry里面的key就是HashMap.put(k,v)中的“k” |
|
返回顶楼 | |
发表时间: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 |
|
返回顶楼 | |
发表时间:2010-12-12
以前看过,后来忘记了。
不过今天看这些讨论,又有新的收获,那就是hashmap的初始数组长度为什么是16. 受教了,另外增长为什么是倍数增长,原来都是有原因的啊。 |
|
返回顶楼 | |