【问题标题】:When exactly does the ordering of the hash map keys are affected,哈希映射键的顺序究竟何时受到影响,
【发布时间】:2016-01-26 21:52:00
【问题描述】:

我知道哈希图中的键顺序无法保证。 如果没有重新哈希或哈希冲突,是否会发生重新排序?

【问题讨论】:

  • 在您添加新密钥之前不会发生这种情况,但它可能因 java 版本而异。
  • 我知道只有一把钥匙就不会这样!!。我的问题是,即使有时我们添加多个键,订单也会保持不变,我想知道订单何时以及为何更改的确切情况。
  • StackFlowed 向您解释说,在您向地图添加另一个键之前,无论当前地图大小如何,它都不会发生。
  • 如果你添加了一个新的键,并且没有重新散列,其余条目的顺序将保持与@987654321相同,@只会将新条目添加到条目列表的开头其中一个桶,迭代器从左到右并按桶顺序返回它们。
  • 长话短说,关于这个问题没有什么真正有用的说法。

标签: java hashmap hashtable hashcode hash-collision


【解决方案1】:

看看这个有趣的link,它详细揭示了 Hashmap 的工作原理: 以下是 put 和 get 工作的说明:

所有具有相同哈希值的键都放在同一个链表(桶)中。具有不同哈希值的键最终可能在同一个桶中。

当用户调用 put(K key, V value) 或 get(Object key) 时,该函数计算 Entry 应该在的桶的索引。然后,该函数遍历列表以查找具有相同键的条目(使用键的 equals() 函数)。

在 get() 的情况下,函数返回与条目关联的值(如果条目存在)。

在 put(K key, V value) 的情况下,如果条目存在,则函数将其替换为新值,否则它会在单个的头部创建一个新条目(根据参数中的键和值)链表。

【讨论】:

    【解决方案2】:

    我们真的不应该担心这个!

    在查看 HashMap 的源代码时,它似乎在内部使用了一个 HashMap.Entry 对象数组,用于查找所需条目的数组索引基于对象的 hashCode() 和大小数组。所以排序与对象的hashCode和Map的大小有关。

    不过,这是一种简化,我只查看了 OpenJDK 6 中的实现。

    您永远不应该依赖实施细节。有一个名为 Map 的接口是有充分理由的:它定义了应该如何使用它。

    【讨论】:

      【解决方案3】:

      特别是在java.util.HashMap 中,条目仅在达到最大阈值时才会移动和重新排序。 addEntry() 方法调用 resize() 方法,该方法转移到新表重新排列键

      768     void addEntry(int hash, K key, V value, int bucketIndex) {
               //
      771         if (size++ >= threshold)
      772             resize(2 * table.length);
      
      
      471    void resize(int newCapacity) {
               //
      479         Entry[] newTable = new Entry[newCapacity];
      480         transfer(newTable);
      481         table = newTable;
      

      【讨论】:

      • 这是重新散列,OP 已将其排除在问题之外。
      猜你喜欢
      • 1970-01-01
      • 2013-01-06
      • 2017-08-28
      • 1970-01-01
      • 1970-01-01
      • 2018-01-29
      • 1970-01-01
      • 2012-08-08
      • 2015-12-26
      相关资源
      最近更新 更多