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 of
HashMap:
此实现为基本的 操作(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)
。但是,在keys
与Comparable
发生碰撞的情况下,存储碰撞元素的箱在超过称为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()的时间复杂度是多少?的主要内容,如果未能解决你的问题,请参考以下文章