调用java.util.HashMap.keySet()有多贵?

时间:2010-04-08 13:53:14

标签: java

我将稀疏矩阵实现为List<Map<Integer,Double>> 要获取第i行的所有条目,请致电list.get(i).keySet()。这次电话有多贵?

我还使用了宝库来替代List<TIntDoubleHashMap>
list.get(i).keys()的费用是多少?

您对如何实现有效的稀疏矩阵有任何进一步的想法吗? 或者您可以在java中提供现有实现的列表吗?

3 个答案:

答案 0 :(得分:5)

取决于实现List和Map的类。如果您正在使用实现java.util.RandomAccess(即ArrayList)的List类,则对get(i)的调用是O(1)。如果它是LinkedList,则它将是O(n)。

- 编辑以显示以下代码段(因为下面的verdy_p读取不好,并且喜欢关闭切线): -

// In HashMap.java, line 867, JDK 1.6.0.24, how much more
// constant time do we want?

public Set<K> keySet() {
    Set<K> ks = keySet;
    return (ks != null ? ks : (keySet = new KeySet()));
}

- 编辑结束 -

在大多数Map实现中对keySet()的调用将是常量时间。

关于遍历keySet()如果使用的是数组支持的Map实现(如HashMap),则keySet()依赖于entrySet(),它返回由数组支持的内部迭代器。因此keySet()的迭代是O(n)。

我还假设大多数(如果不是全部)数组支持的Map实现都是这种情况。

对于SortedMap实现(如TreeMap),迭代其键将类似于从最低到最大键迭代树。这相当于失败的二进制搜索,即O(n)。

两种情况似乎都是O(n)。如果您使用Eclipse,您实际上可以查看实现java类的代码,并更好地了解它们的复杂性。

对于java.util.concurrent下的类(如ConcurrentHashMap),您必须考虑其他因素来确定它们的价格。


要扩展一点,如果使用链表,list.get(i).keyset()将为O(n)。使用ArrayList,它将是O(1)。遍历键集取决于您是使用数组支持的Map(HashMap)还是SortedMap(TreeMap)。在这两种情况下,遍历将是O(n),前者显着比后者更快,因为数组遍历总是比遍历指针(或Java特定情况下的引用)更快。 p>

现在,如果您将两者 list.get(i).keySet()和集合的迭代考虑在内,使用链接列表实现, 将是O(n ^ 2)。因此,不应该使用list.get(i).keySet(),而应使用迭代器(请参阅下面的 伪代码 ,为了清晰起见,它会避免使用通用语法)

对于未实现java.util.RandomAccess(如LinkedList)的列表,这是O(n ^ 2):

for( int i = 0; i < list.size(); i++ )
{
   Set keySet = list.get(i).keySet();
   for( Integer key : keySet.iterator() )
   {
      ... stuff (assuming constant time) ...
   }
}

对于相同类型的List实现,这是O(n):

for( Map m : list.iterator() )
{
   for( Integer key : m.keySet() )
   {
      ... stuff (assuming constant time) ...
   }
}

答案 1 :(得分:2)

它的价格便宜,因为它是一种观点。

来自jdk7 source line 884

public Set<K> keySet() {
    Set<K> ks = keySet;
    return (ks != null ? ks : (keySet = new KeySet()));
}

Trove可能更快,因为与Java Collection Frameworks不同,它可以直接使用原语而无需昂贵的装箱/拆箱。

答案 2 :(得分:2)

根据Sparse matrices / arrays in Java,Colt库包含此功能;潜入他们的Javadoc API,这似乎是真的,时间也包括在内。

此外,您的实现似乎没有使用列式稀疏性(您只在行上使用了哈希映射)。他们这样做,并且针对整数和双精度进行了优化,就像在Trove中一样(但是在标准的Java情况下,它使用的是具有相当大开销的对象)。我推荐柯尔特。

相关问题