精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2013-01-11
最后修改:2013-01-11
forchase 写道 引用 void transfer(Entry[] newTable) { Entry[] src = table; int newCapacity = newTable.length; for (int j = 0; j < src.length; j++) { Entry<K, V> e = src[j]; if (e != null) { src[j] = null; do { Entry<K, V> next = e.next; int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } while (e != null); } } } 这个方法里面的“e.next = newTable[i]”没太懂它的意图,是让“newTable[i]”的下一个节点指向自己,还是赋为空,“newTable[i] = e”这个操作是不是说明了上面那个赋值操作是让“newTable[i]”的下一个节点指向自己,让它的下一个节点指向自己有其他用途吗,求指导~~ //newTable是新的散列表,this.table是旧的散列表,这个方法的任务就是把this.table中 //的Entry移动到newTable中,移动的同时重新散列。要注意的是,Entry是链表结构,table[i]和newTable[i] //均指向一个链表的首元素。 void transfer(Entry[] newTable) { Entry[] src = table; int newCapacity = newTable.length; for (int j = 0; j < src.length; j++) { /*逐个移动旧散列表中的链表*/ Entry<K, V> e = src[j]; /*e是一个链表的首元素*/ if (e != null) { src[j] = null; /*从旧表中移除链表引用,边复制边移除可以避免复制过程中占用额外的内存*/ do { /*对需要移动的链表中的每个元素逐一进行重新散列*/ Entry<K, V> next = e.next; /*先缓存链表的下一个元素。因为后续运算中e.next会被覆盖,因此要在一开始缓存。*/ int i = indexFor(e.hash, newCapacity); /*算出当前元素的新散列位置*/ e.next = newTable[i]; /*别忘记newTable[i]指向一个链表的首元素。这行和下面一行把e插入到这个链表的前端*/ newTable[i] = e; e = next; /*继续处理旧链表中的下一个元素*/ } while (e != null); /*如果e已是链表最后一个元素,退出循环*/ } } } |
|
返回顶楼 | |
发表时间:2013-01-11
引用 不是让它的下一个节点指向自己 [i] e.next = newTable[i]; newTable[i] = e; e = next; 这段code中,是将原来的Array[j]上的链表移到新申请的数组的某个节点(数组下标有indexFor计算)最好画个图就clear了 嗯,我忽略了外面那个while循环了,呵呵 |
|
返回顶楼 | |
发表时间:2013-01-16
请教一下,重新散列的时候,同一个槽内的元素应该是拥有相同的hash,再次散列后也应该是落在同一个槽内吧?
|
|
返回顶楼 | |
发表时间:2013-01-17
sky_kk 写道 请教一下,重新散列的时候,同一个槽内的元素应该是拥有相同的hash,再次散列后也应该是落在同一个槽内吧?
/** * 通过hash code 和table的length得到对应的数组下标 * * @param h * @param length * @return */ static int indexFor(int h, int length) { return h & (length - 1); } |
|
返回顶楼 | |