hashTable是一个数组的链表,本身是一个 Entry[] 数组,里面的一个对象放的是一个链表的结构。如果一个HashTable中key的hashcode相同,那么它就放在同一个链表中。
回到rehash中,在扩展容器本身的容量时,每个对象(key,value)的位置也会相应的发生调整。
源码内容如下:
protected void rehash() {
int oldCapacity = table.length;
Entry[] oldMap = table;
// overflow-conscious code
int newCapacity = (oldCapacity << 1) + 1;
if (newCapacity - MAX_ARRAY_SIZE > 0) {
if (oldCapacity == MAX_ARRAY_SIZE)
// Keep running with MAX_ARRAY_SIZE buckets
return;
newCapacity = MAX_ARRAY_SIZE;
}
Entry[] newMap = new Entry[newCapacity];
modCount++;
threshold = (int)(newCapacity * loadFactor);
table = newMap;
for (int i = oldCapacity ; i-- > 0 ;) {
for (Entry
old = oldMap[i] ; old != null ; ) {
Entry
e = old;
old = old.next;
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
e.next = newMap[index];
newMap[index] = e;
}
}
}
其中关键点在于下面这个for循环中,它先去从后向前的遍历数组,然后第二层循环去遍历数组中每个对象链表,重新计算链表中每一个节点的位置,这样两层循环下来,各个节点的位置就调整好了,容器容量也扩展了。
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;
}
}