java.util.HashMap类'keySet()方法的时间复杂度是多少?

时间:2009-12-05 01:44:04

标签: java algorithm hashmap complexity-theory

我正在尝试实现平面扫描算法,为此我需要知道java.util.HashMap class' keySet()方法的时间复杂度。我怀疑它是O(n log n)。我是对的吗?

澄清点:我在谈论keySet()方法的时间复杂性;迭代返回的Set将明显花费O(n)时间。

6 个答案:

答案 0 :(得分:15)

实际上,获取密钥集是O(1)并且便宜。这是因为HashMap.keyset()返回与HashMap关联的实际KeySet对象。

返回的Set 不是键的副本,而是实际HashMap状态的包装器。实际上,如果你更新集合,你实际上可以改变HashMap的状态;例如在集合上调用clear()将清除HashMap!

答案 1 :(得分:5)

肯定会是O(1)。它正在做的就是在HashMap上返回一个包装器对象。

如果你在谈论遍历键集,那么这是O(n),因为每个next()调用都是O(1),这需要执行n次。

答案 2 :(得分:2)

这应该在O(n)时间内可行...哈希映射通常实现为大型桶阵列,桶的大小(通常)与哈希映射的大小成正比。为了检索密钥集,必须迭代桶,并且对于每个集合项,必须检索密钥(通过中间集合或直接访问存储桶的迭代器)...

**编辑:正如其他人所指出的那样,实际的keyset()方法将在O(1)时间内运行,但是,迭代密钥集或将其转移到专用集合将是O(n)操作。不太确定你要找哪一个**

答案 3 :(得分:0)

Java集合有很大的空间,因此不需要花费太多时间。我认为,这种方法是O(1)。这个系列只是坐在那里。

答案 4 :(得分:0)

要解决“迭代返回的Set显然需要O(n)时间”的注释,根据HashMap的{​​{3}},这实际上是不正确的:

  

在集合视图上进行迭代需要的时间与HashMap实例的“容量”(存储桶数)及其大小(键值映射数)成正比。因此,如果迭代性能很重要,那么不要将初始容量设置得太高(或负载因子太低)是非常重要的。

因此,换句话说,对返回的Set进行迭代将花费O(n + c),其中n是地图的大小,c是地图的容量,而不是{{1 }}。如果选择了不合适的初始容量或负载因子,则O(n)的值可能会超出迭代时间的地图实际大小。

答案 5 :(得分:0)

切线答案:

  

...遍历返回的Set显然将花费O(n)时间。

实际上并非总是 正确:

  • 使用HashMap创建new HashMap<>()确实如此。最坏的情况是让所有N键都位于同一哈希链中。但是,如果地图自然增长,则哈希数组中仍将有N个条目和O(N)个时隙。因此,迭代条目集将涉及O(N)个操作。

  • 如果HashMap是用new HashMap<>(capacity)创建的,并且估计值为capacity奇异(太大),则为假。然后,将需要O(Cap) + O(N)个操作来迭代条目集。如果我们将Cap视为变量,即O(max(Cap, N)),可能会比O(N)差。

尽管有一个转义子句。由于capacity是当前int API中的HashMap,因此Cap的上限是2 31 。因此,对于真正的大CapN而言,复杂度为O(N)

另一方面,N受可用内存量的限制,实际上,{{1},您需要按2 38 字节(256GBytes)顺序排列的堆}超过可能的最大N值。对于如此大小的地图,最好使用针对大型地图调整的哈希表实现。还是不使用过大的容量估算值!