【问题标题】:Handling the key collision in Hashmap处理 Hashmap 中的键冲突
【发布时间】:2013-12-04 21:55:04
【问题描述】:

我为 Hashmap 的 put(K key, V value) 找到的 code。如果发生冲突,此方法会替换该值,它不会将Entry 添加到存储桶的 LinkedList。
我在这里缺少什么?

【问题讨论】:

  • 我认为您将冲突(相同的哈希码)与等于(实际上等效)混为一谈。
  • 可能是。我想看看java是如何处理冲突的。

标签: java collections hashtable


【解决方案1】:

您不能在 HashMap 中多次使用相同的密钥。这就是为什么值被替换而不是仅仅创建一个新的Map.Entry<K,V>

【讨论】:

    【解决方案2】:

    你没有错过任何东西。 Java 的Maps 的一般约定是每个键都有一个值。 如果您想为每个键保存多个值,则必须使用 Apache Commons' MultiMap 之类的东西,或者通过 Map<K, List<V>> 自己实现类似的东西。

    【讨论】:

    • 你是说Java HashMap 不处理冲突场景。它只是替换值。是这样吗?
    • @HimanshuYadav 请注意,内部链表适用于具有相同哈希码的所有键 - 不适用于相等的键(在这种情况下,值将被替换,如前所述)
    【解决方案3】:

    你为什么这么认为?相关行如下:

    计算内表索引:

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

    遍历table[i]处的链表并搜索键是否已经包含:

    391 for (Entry<K,V> e = table[i]; e != null; e = e.next) {
    392     Object k;
    393     if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
    

    键已包含 => 替换值...

    394         V oldValue = e.value;
    395         e.value = value;
    396         e.recordAccess(this);
    

    ...并返回旧值

    397         return oldValue;
    398     }
    

    否则继续循环

    399 }
    

    我们在链表的末尾,我们还没有找到键,所以它还没有被包含。所以让我们添加一个新条目:

    402 addEntry(hash, key, value, i);
    

    【讨论】:

    • Line 394-396 是我的问题。为什么要替换旧值?
    • 参见 Map#put 的规范:“(...)如果映射先前包含键的映射,则旧值将替换为指定值。(...)。这是不是“冲突”,正如其他人已经在他们的答案中所说的那样。如果两个键具有相同的哈希码但不相等,则会发生冲突。在这种情况下,不会发生替换!(参见第 402 行)。
    • 如果您需要为每个键保存多个值,请考虑使用 List 作为值或提供 MultiMap 的第三方库(例如 commons.apache.org/proper/commons-collections/javadocs/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多