【问题标题】:how are buckets created in hashmap?如何在 hashmap 中创建存储桶?
【发布时间】:2015-05-03 19:23:33
【问题描述】:

我对哈希映射的内部工作有点困惑。 我创建了一个默认容量为 16 的 Hashmap,并且我的键类始终返回一个哈希码值 1。因此,当我将第 13 个元素输入到该地图时,它将使地图大小翻倍。
1. hash map 中会有多少个桶?
2. hash map 是否按需创建新的bucket(即当hash code 与任何现有bucket 的hash code 值不匹配时)?

【问题讨论】:

  • 由于每个元素的哈希码都是一个,所以不会创建新的桶,所有元素都将进入同一个桶并由LinkedList进一步管理。

标签: java collections


【解决方案1】:

虽然有点晚了,但这可能会帮助其他用户寻找这个问题的答案。

关于你的第一个问题,哈希图中会有多少个桶?-- 如果您在实例化 HashMap 时未在构造函数参数中指定,则默认容量为 16 个桶。

现在我们来看第二个问题,即hash map 是否按需创建一个新的bucket(即当hash code 与任何现有bucket 的hash code 值都不匹配时)?

看看Hashmap的put方法here的实现会很有趣。

public V put(K key, V value) {

    if (key == null)
        return putForNullKey(value);

    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);

    for (Entry<K, V> e = table[i]; e != null; e = e.next) {
        Object k;

        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }
    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

如果你仔细观察,接受 key 的 hashmap 作为参数的方法 hash 在 put 方法中被调用。这种方法的作用是防止质量差的散列函数。使用此 indexFor 方法后,标识将插入元素的索引(桶)。此方法返回的索引始终指向现有存储桶。因此,不会出现密钥的哈希码指向不存在的存储桶的情况。

那么hashmap什么时候创建一个新的bucket呢?它在javase docs 中得到了巧妙的解释。

它说:“HashMap的一个实例有两个影响其性能的参数:初始容量和负载因子。容量是哈希表中的桶数,初始容量只是哈希时的容量表被创建。负载因子是哈希表在其容量自动增加之前被允许达到多满的量度。当哈希表中的条目数超过负载因子和当前容量的乘积时,哈希表表被重新散列(即内部数据结构被重建),使得散列表的桶数大约是两倍。”

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    当您使用默认容量 (16) 创建 HashMap 时,您会使用 16 个存储桶(即容量 == 存储桶数量)创建它。

    1. 容量翻倍时,桶数翻倍。

    2. hashCode 始终与某个现有存储桶匹配,因为模数 N(其中 N 是当前容量)应用于计算的哈希以找到它所属的存储桶。

    【讨论】:

      【解决方案3】:

      我更多来自 C#,但 Java 与它非常相似 :) 所以,如果这里有什么问题,请原谅我。请随时更正。

      无法轻易得知可用存储桶的数量。它取决于地图中的元素数量(负载因子)。负载率保持在总容量的 75% 左右。这与以下事实有关,如果有两个相同的哈希值,其中一个必须重新哈希(以获得地图中的另一个位置)-> 75% 是性能和大小之间的一个很好的权衡。每当超过 75% 时,大小就加倍(即 16 的 75% 是 12;第 13 个元素的大小加倍)。无论如何这也是第二个问题的答案。

      【讨论】:

        猜你喜欢
        • 2020-10-31
        • 2019-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-06
        • 2020-12-05
        相关资源
        最近更新 更多