【问题标题】:Java HashMap key hashing [duplicate]Java HashMap键散列[重复]
【发布时间】:2021-10-15 05:16:56
【问题描述】:

如果我在 hashmap 中输入一个 key 和 value,并且基于 key hashcode 生成的索引大于 15,而 map 大小仍然小于阈值 12,会发生什么?

提前致谢。

【问题讨论】:

    标签: java hashmap hashcode


    【解决方案1】:

    HashMap 通常会对 hashCode() 方法提供的值执行模运算,以便将整数范围映射到其内部数组的有效索引范围内。

    这可能会导致冲突(不同的哈希值映射到同一个索引),这是一个单独的主题,并且还会导致 HashMap 的 O(1) 预期时间的降级。需要注意的是,假设您的 hashCode() 实现是均匀分布的。

    在良好的 HashMap API 中,您无需担心内部数组大小或冲突。这是由实现在内部以各种方式处理的。

    在 Java 的 HashMap API 中没有公开可见的“阈值”。你能得到的最接近的是:

    HashMap(int initialCapacity, float loadFactor)
    

    这里,你提到的阈值相当于loadFactor。根据 Java 文档:

    “作为一般规则,默认加载因子 (.75) 在时间和空间成本之间提供了很好的折衷。较高的值会减少空间开销但会增加查找成本(反映在 HashMap 类的大多数操作中,包括get和put)。在设置其初始容量时应考虑map中的预期条目数及其负载因子,以尽量减少rehash操作的次数。如果初始容量大于最大条目除以负载因子,将不会发生重新哈希操作。”

    基本上这意味着如果 HashMap 中的冲突太多,它将扩大其当前数组大小并重新散列所有当前键,从而(希望)产生更均匀的分布。这应该具有在 HashMap 的一系列添加或删除中保持预期的 O(1) 复杂度的效果。

    【讨论】:

      【解决方案2】:

      让我给你一个更广泛的图片,而不是只关注 Java 的特定数据类型 HashMap,因为你的问题包括 hashcode 标签,在我看来,你对更通用的图片感兴趣 - 如何散列函数是否有效。

      索引归一化

      是你需要了解的。

      通常,索引规范化如何发生完全取决于特定数据结构的实现,该数据结构将输入散列到键(如HashTable/HashMap)以及无论它是什么实现,可以肯定地说:

      您的哈希函数 h(x) 应该负责始终且始终如一地生成一个整数,该整数位于后备数组的有效索引范围内。

      在许多实现中,散列函数可能会返回一个很长的(并且可能是负数)整数,这通常由 index normalization 解决,它只是对该长整数(作物、使负数为正等)。

      对于 Java 的 HashMap 实现,hashCode() 是:

      @HotSpotIntrinsicCandidate
      public native int hashCode();
      

      这意味着,该实现被委托给底层。

      但在大多数情况下,您可以假设它将使用后备数组长度的模(存储桶数),这意味着它永远不会超过该数组的长度(因此,您的哈希图的大小) .

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-17
        • 1970-01-01
        • 1970-01-01
        • 2013-02-26
        • 2017-07-11
        • 2023-03-19
        相关资源
        最近更新 更多