java - 为什么 Java HashMap 实现在调整大小时使用 transfer() 而不是 put()?

标签 java hashmap

在 Java 7 中 HashMap实现,在 resize方法,它调用 transfer 将旧元素移动到新表。为什么他们写了一个新方法而不是调用 put所有旧元素?由于 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 压力)。
  • 它可以重复使用 hash存储在 Entry 中的值对象从而避免必须调用 Object.hashValue在 map 中已经存在的每个键上(理论上这可能是一项昂贵的操作)。

  • 基本上:如果resize只是在 put 方面实现的它必须重新做很多很容易避免的工作。
    JDK 的更高版本明显更加复杂 HashMap更复杂的实现 transfer方法(或等价物)被实现。
    还值得指出的是,在 JDK 本身中完成时,即使以不那么“简单”的代码为代价的微小性能提升通常也是值得的:因为 HashMap基本上每个 Java 程序都使用它,让它尽可能地提高性能,但以稍微降低可读性为代价通常是值得的权衡。同样的道理也适用于 不是 同样适用于我们“凡人”编写的大多数其他软件。

    关于java - 为什么 Java HashMap 实现在调整大小时使用 transfer() 而不是 put()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68010999/

    相关文章:

    rust - 在 Rust 中使用 Box<> 和 HashMap<>

    java - 从 HashMap 中获取 k 个最大值

    java - 如何用数组列表填充 HashMap ?

    java - (true != false != true) 与 (false != true != false) 有何不同?

    java - Scope 如何影响 Bean 的对象?

    java - 更改多个 Java 实例中的变量

    java - jmeter是否使SOAP请求超时

    java - 修复 Java 中的移动逻辑

    java - 从 HashMap 中返回特定值

    java - HASHMAP - 阈值和负载因子以及容量