为什么 Java HashMap 实现在调整大小时使用 transfer() 而不是 put()?
Why does the Java HashMap implementation use transfer() instead of put() when resizing?
在Java7HashMap
实现中,在resize
方法中,它调用了transfer
which moves old elements to a new table. Why have they written a new method instead of calling put
with all the old elements? The resize won't be triggered again due to threshold。调用 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);
}
}
}
一个重要的区别是 transfer
可以通过两种方式利用每个条目的 Entry
个对象已经存在的事实:
- 它可以重用
Entry
对象本身以避免分配新对象(从而避免内存分配,从而减少 GC 压力)。
- 它可以重用存储在
Entry
对象中的 hash
值,从而避免必须在映射中已有的每个键上调用 Object.hashValue
(这在理论上可能是一项昂贵的操作).
基本上:如果 resize
仅根据 put
实施,则必须重新做很多可以轻松避免的工作。
JDK 的更高版本具有明显更复杂的 HashMap
实现,其中实现了更复杂的 transfer
方法(或等效方法)。
还值得指出的是,在 JDK 本身中完成时,即使以较少“简单”代码为代价的微小性能提升通常也是值得的:因为 HashMap
基本上用于每个Java 程序,以稍微降低可读性成本为代价尽可能地提高性能通常是值得的权衡。同样的推理不同样适用于我们“凡人”编写的大多数其他软件。
在Java7HashMap
实现中,在resize
方法中,它调用了transfer
which moves old elements to a new table. Why have they written a new method instead of calling put
with all the old elements? The resize won't be triggered again due to threshold。调用 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);
}
}
}
一个重要的区别是 transfer
可以通过两种方式利用每个条目的 Entry
个对象已经存在的事实:
- 它可以重用
Entry
对象本身以避免分配新对象(从而避免内存分配,从而减少 GC 压力)。 - 它可以重用存储在
Entry
对象中的hash
值,从而避免必须在映射中已有的每个键上调用Object.hashValue
(这在理论上可能是一项昂贵的操作).
基本上:如果 resize
仅根据 put
实施,则必须重新做很多可以轻松避免的工作。
JDK 的更高版本具有明显更复杂的 HashMap
实现,其中实现了更复杂的 transfer
方法(或等效方法)。
还值得指出的是,在 JDK 本身中完成时,即使以较少“简单”代码为代价的微小性能提升通常也是值得的:因为 HashMap
基本上用于每个Java 程序,以稍微降低可读性成本为代价尽可能地提高性能通常是值得的权衡。同样的推理不同样适用于我们“凡人”编写的大多数其他软件。