【问题标题】:What is the time complexity of HashMap.containsKey() in java?java中HashMap.containsKey()的时间复杂度是多少?
【发布时间】:2012-02-13 22:43:08
【问题描述】:

我要知道:java中HashMap.containsKey()的时间复杂度是多少?

【问题讨论】:

  • @OlegSklyar 这个问题对我有帮助,因为我必须自己实现一个 HashMap。
  • @trinity420 因此,当您对 API 有疑问时,这有理由不阅读 API 文档?
  • Java 8:最佳情况 O(1),最坏情况 O(log n)
  • 如果最坏的情况不是 O(1)。检查这个:stackoverflow.com/questions/8923251/…

标签: java performance hashmap time-complexity


【解决方案1】:

来自API doc ofHashMap

此实现为基本的 操作(get 和 put),假设散列函数分散 桶中的元素。

由于containsKey() 只是一个丢弃检索到的值的get(),它是 O(1)(假设哈希函数再次正常工作)。

【讨论】:

  • 这是我之前的想法。但这是不正确的。看看 Jigar Joshi 的回答。对于不允许空值的Hashtable,您的答案是正确的。
  • @AlexR:我认为您完全误解了 Jigar 答案中的代码。它与空值完全无关,并且 for 循环仅循环遍历单个存储桶中的条目链接列表,如果如我的回答中所述两次,哈希函数完成其工作,则为 O(1)。
  • @Tom Hawtin - tackline:我不认为这是大多数人需要担心的情​​况(不,不包括编写 servlet 容器的人)。
  • @TomHawtin-tackline,没有流行的哈希映射实现有点奇怪。使用树进行碰撞。所以最坏的情况是 O(logN),否则是 O(1)。
  • @bestsss 是的。这是显而易见的数据结构,但确实需要键类型同时支持散列和排序接口,并且要始终如一地做到这一点。此外,性能中的常数因素在现实生活中也很重要。对于表现良好的情况,碰撞会变慢。不过,这是我希望在 java.util 中看到的地图实现。
【解决方案2】:

通常是 O(1),但是如果我们使用了一个错误的 hashCode 函数,我们需要将多个元素添加到一个桶中,这样在最坏的情况下它可能是 O(n)。

【讨论】:

    【解决方案3】:

    一般是O(1),但最坏的情况是O(n)

     public boolean containsKey(Object key) {
      352           return getEntry(key) != null;
      353       }
      354   
      355       /**
      356        * Returns the entry associated with the specified key in the
      357        * HashMap.  Returns null if the HashMap contains no mapping
      358        * for the key.
      359        */
      360       final Entry<K,V> getEntry(Object key) {
      361           int hash = (key == null) ? 0 : hash(key.hashCode());
      362           for (Entry<K,V> e = table[indexFor(hash, table.length)];
      363                e != null;
      364                e = e.next) {
      365               Object k;
      366               if (e.hash == hash &&
      367                   ((k = e.key) == key || (key != null && key.equals(k))))
      368                   return e;
      369           }
      370           return null;
      371       }
    

    【讨论】:

    • 那就是Ω(1)O(n)
    • 查看 mishadoff 的回答以了解最坏情况的解释。
    • Java 1.8 最坏的情况是 O(log n)。
    【解决方案4】:

    containsKey 的时间复杂度在 JDK-1.8 中发生了变化,正如其他人所说,在理想情况下它是 O(1)。但是,在keysComparable 发生碰撞的情况下,存储碰撞元素的箱在超过称为TREEIFY_THRESHOLD 的某个阈值(等于8)后不再是线性的,

    /**
     * The bin count threshold for using a tree rather than list for a
     * bin.  Bins are converted to trees when adding an element to a
     * bin with at least this many nodes. The value must be greater
     * than 2 and should be at least 8 to mesh with assumptions in
     * tree removal about conversion back to plain bins upon
     * shrinkage.
     */
    static final int TREEIFY_THRESHOLD = 8;
    

    换句话说,TreeNodes 将用于(类似于TreeMap 中的那些)来存储箱,(即:红黑树结构)这给我们留下了O(lgn) 的复杂性以防万一碰撞。

    这同样适用于get(key),其中两种方法都在内部调用getNode

    注意:n这里是bin的大小,而不是HashMap的大小

    【讨论】:

      猜你喜欢
      • 2013-05-21
      • 2011-02-15
      • 1970-01-01
      • 1970-01-01
      • 2014-10-04
      • 1970-01-01
      • 2018-11-24
      • 2014-05-27
      相关资源
      最近更新 更多