java - HashMap 不会按照默认值重新哈希

标签 java hash hashmap hashtable

根据 Java 文档

An instance of HashMap has two parameters that affect its performance: initial capacity and load factor. The capacity is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created. The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased. When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the hash table is rehashed (that is, internal data structures are rebuilt) so that the hash table has approximately twice the number of buckets.

 the default initial capacity is 16 and the default load factor is 0.75.

根据上述,HashMap 的阈值是 12(16 * 0.75),并且 HashMap 在放入第 13 个元素时应该重新哈希。

我创建了一个空的 HashMap 并在其中放入了 16 个元素。我在 Debug模式下运行它。当放置第 13 个元素时,我检查了调试变量,并惊讶地发现阈值仍然是 12(而不是 24) 并且表数组仍然包含 16 条目(而不是 32) 。仅在放入第 16 个元素后,哈希表才会重新哈希,使阈值 24(32 * 0.75)

我错过了什么吗?

最佳答案

我在HashMap(Java 7)的源代码中找到了答案。输入一个值将运行以下代码:

public V put(K key, V value) {
    [...]
    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

有趣的调用是添加条目的方法。我们来看看这个方法的来源:

void addEntry(int hash, K key, V value, int bucketIndex) {
    if ((size >= threshold) && (null != table[bucketIndex])) {
        resize(2 * table.length);
        hash = (null != key) ? hash(key) : 0;
        bucketIndex = indexFor(hash, table.length);
    }
    createEntry(hash, key, value, bucketIndex);
}

正如我们所见,仅当大小超过阈值并且计算出的存储桶(用于放置条目)不为空时,才会进行大小调整。

这种行为是有道理的。只要每个条目进入一个空桶,就不需要调整大小,因为每个条目都位于桶列表的第一个位置,因此很容易找到。 这一切都与性能有关。事实上,有很多实现细节都表现得非常好。

编辑(因为 Java 6 和 Java 7 之间存在差异):

上面的源代码来自Java 7。实际上,在Java 6中,调整大小行为仅取决于大小和阈值。这是 Java 6 中 addEntry 方法的来源:

void addEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
    if (size++ >= threshold)
        resize(2 * table.length);
}

这实际上意味着 HashMap 实现从 Java 6 更改为 Java 7(由于性能原因)。

关于java - HashMap 不会按照默认值重新哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24503325/

相关文章:

java - 如何将属性转换为字符串?

java - 无法将 Slf4j 与 lombok 一起使用

java - 在 LINUX 操作系统中从 JAVA 应用程序创建用户

swift - 在 Swift 中实现哈希组合器

java - 在 Java 中使用 HashMap 创建表

Java HashMap 在 get() 调用时返回 null

java - JDBC 查询返回值

java - 由于 AsyncTask 是一个单独的类,我如何才能将 OnPostExecute() 的结果传递给主要 Activity ?

java - 从多个输入字符串生成确定性唯一固定长度文件名字符串

Javascript 哈希短字符串的异常行为