java中HashMap.containsKey()的时间复杂度是多少?

Posted

技术标签:

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

我要知道:

【问题讨论】:

@OlegSklyar 这个问题对我有帮助,因为我必须自己实现一个 HashMap。 @trinity420 因此,当您对 API 有疑问时,这有理由不阅读 API 文档? Java 8:最佳情况 O(1),最坏情况 O(log n) 如果最坏的情况不是 O(1)。检查这个:***.com/questions/8923251/… 【参考方案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的大小

【讨论】:

以上是关于java中HashMap.containsKey()的时间复杂度是多少?的主要内容,如果未能解决你的问题,请参考以下文章

机一次cpu100%的线上故障

java把数据以key-value形式放到内存中,以后匹配key值就可以读取数据。大概想法有,求详细代码!!

校招笔试题编程技巧总结

java中import的问题

java中this的用法?

java中native的用法