在 Java 7HashMap实现中resize,它调用transfer将旧元素移动到新表的方法。为什么他们编写了一个新方法而不是put使用所有旧元素进行调用?由于阈值,不会再次触发调整大小。调用put使代码更清晰。
/**
* Transfers all entries from current table to newTable.
*/
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
一个重要的区别是transfer可以通过Entry两种方式利用每个条目的对象已经存在的事实:
Entry对象本身以避免必须分配新对象(从而避免内存分配,从而减少 GC 压力)。hash存储在Entry对象中的值,从而避免必须调用Object.hashValue映射中已经存在的每个键(理论上这可能是一项昂贵的操作)。基本上:如果resize只是简单地实现put它就必须重新做很多可以轻松避免的工作。
JDK 的更高版本具有更复杂的HashMap实现,其中实现了更复杂的transfer方法(或等效方法)。
还值得指出的是,在 JDK 本身中完成时,即使以不那么“简单”的代码为代价的微小的性能提升通常也是值得的:因为HashMap基本上每个 Java 程序都使用它,因此它在可读性稍差的代价通常是值得权衡的。同样的道理也不能等同于大多数其他软件,我们“凡人”写申请。
| 归档时间: |
|
| 查看次数: |
72 次 |
| 最近记录: |