【发布时间】:2012-08-07 20:08:21
【问题描述】:
有人知道Java HashMap中keySet的摊销分析是什么吗? O(1)?
正在遍历它们O(n)?
【问题讨论】:
有人知道Java HashMap中keySet的摊销分析是什么吗? O(1)?
正在遍历它们O(n)?
【问题讨论】:
map.keySet() 只是返回一个对存储在映射中的键集的引用,因此它显然是一个 O(1) 操作。
然后迭代是对该集合的循环,该集合本身在内部使用映射的桶上的循环,因此操作所需的时间与 n+m 成正比,其中 n 是键集的大小,m 是地图的容量.
因此,如果您的地图容量非常大,只有一个条目,那么即使只有一个键,对 keySet 的迭代也会遍历所有桶。
不知道你是如何用 big-o 表示法翻译的。
我刚刚对两张地图进行了快速测试,每张地图都有一个条目。一张地图的容量为 1000 万,另一张的容量为 1。对 keyset(两种情况下都是一项)的迭代需要大地图的 3,500 倍时间(18,843,092 ns 对 5434 ns)。
ps:和javadoc of HashSet 说的差不多:
迭代这个集合需要的时间与 HashSet 实例的大小(元素的数量)加上支持 HashMap 实例的“容量”(桶的数量)的总和成正比。因此,如果迭代性能很重要,那么不要将初始容量设置得太高(或负载因子太低),这一点非常重要。
【讨论】:
for (Key k : map.keyset()) 是对键集的迭代,它恰好是一个集合。这相当于使用迭代器。如果您查看集合的迭代器的代码,您会发现它循环遍历每个映射桶,无论集合中的项目数量是多少。因此,如果集合只有一个项目,但地图有 10,000,000 个项目,则迭代该集合将意味着迭代 10,000,000 个地图的桶,仅获取一个项目。
您可以检查source code 的keySet。
基于 this 迭代 Set 是 O(n)
【讨论】: