【问题标题】:Map behaviour with duplicate key具有重复键的映射行为
【发布时间】:2013-01-17 09:56:20
【问题描述】:

HashMap 通常用最新的值替换它的值。但是我读过的一篇文章提到了它,因为如果添加重复值,它会保留一个链表。

Read the "What will happen if two different objects have same hashcode"

但是我没有发现连 ConcurrentHashMap 都没有维护这样一个列表?

哪些集合在列表中维护重复项,如果是,如何使用 get("key") 方法识别相关对象?

【问题讨论】:

  • 重复值!= 相同的哈希码
  • 您是在问如何为一个键存储多个值,或者如何解决基于哈希的映射中的哈希冲突?
  • 是的,这在哈希映射中不受支持吗?
  • HashMap 中,key 元素被分成称为桶的组(例如,最初有 16 个桶)。同一桶中的元素在其哈希码中有一些共同点(简化,但想象一下最后 4 位是相同的)。因此,您可以看到同一个存储桶中可能存在许多键。如果要查找值,则根据 Key 的哈希码选择存储桶,遍历元素。当两个键具有相同的哈希码时,调用equals() 来检查完全匹配。如果不匹配,将存储两个不同的条目,否则将覆盖该值。
  • 那么那个有多个对象的桶会把它存储为一个链表对吗?

标签: java collections


【解决方案1】:

“列表”实际上是对链表对象结构的重新实现。这是 HashMap 用来存储键和值的 Entry 类:

static class Entry<K,V> implements Map.Entry<K,V> {
    final K key;
    V value;
    Entry<K,V> next;  <-- This one refers to the next element
    int hash
..
}

因此,LinkedList 没有显式实现。

文章讨论的是两个键具有相同的哈希码会发生什么。然后它当然会存储两个键值对。如果这两个键是equal(),那么它将替换值。

HashMap 的详细工作原理:请参阅我对这个问题的回答:Best practices on what should be key in a hashtable

【讨论】:

    【解决方案2】:

    以下是哈希图(通常)的工作方式:

    Hashmaps 保存了一个桶的集合,用来放置东西。当您插入某些内容时,哈希函数将应用于您要插入的键。生成的“哈希”指示将数据放入哪个存储桶。两个不同的键可以散列到同一个存储桶。这意味着,例如,当您将散列到存储桶 10 的第二个项目插入时,java 实现必须将您的新项目添加到跟踪存储桶 10 中项目的链表的末尾。

    仅仅因为两个项目存储在同一个存储桶(链表)中并不意味着它们具有相同的键。这只是意味着它们的键碰巧散列到相同的值(或等效值以散列桶的数量为模,准确地说)。

    【讨论】:

      【解决方案3】:

      ConcurrentHashMap 中的“并发”是指线程安全,与一个键存储多个值无关。

      您可以在这里找到解决问题的方法:HashMap with multiple values under the same key

      【讨论】:

        【解决方案4】:

        在这里你可以看到数组是哈希码,如果两个对象 A2 和 B2 具有相同的哈希码,那么它们将被添加到同一个桶中。

        但如果对象 A2 和 A3 具有相同的哈希码并在 equals() 上返回 true,则对象 A2 将被 A3 替换。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-11-06
          • 2023-03-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多