在Java中使用List或Map调用size()有多贵?或者如果频繁访问,最好将size()的值保存在变量中?
答案 0 :(得分:13)
答案是它取决于实际的实现类。对于某些Map
和Collection
类,size()
是一种廉价的常量操作。对于其他人来说,可能需要对会员进行统计。
Java Collections Cheatsheet (V2)通常是此类信息的良好来源,但主机服务器目前有点不适。
“coderfriendly.com”域名已不复存在,但我在scribd.com上追踪了the cheat-sheet的副本。
通过查看源代码,size()
的成本也很明显。 (这是一个“实现细节”,几乎可以保证不会改变标准集合类。)
<强>后续强>
不幸的是,cheatsheet只记录了队列实现的size
的复杂性。我认为这是因为所有其他收藏品都是O(1)
;看@seanizer的答案。
答案 1 :(得分:3)
对于ArrayList
,实现就像
public int size() {
return lastIndex - firstIndex;
}
所以不要过头
您可以查看源代码,了解所需Impl 的详细信息。
注意:给出的来源是来自openjdk
答案 2 :(得分:3)
List
和Map
是接口,所以无法说出。对于Java Standard API中的实现,大小通常保存在字段中,因此与性能无关。
答案 3 :(得分:3)
对于大多数集合,调用size()
是一个固定时间操作。但是有一些例外。一个是ConcurrentLinkedQueue。来自the size() method的Javadoc:
请注意,与大多数集合不同,此方法不是恒定时间操作。由于这些队列的异步性质,确定当前元素数需要进行O(n)遍历。
所以我担心没有通用的答案,你必须查看你正在使用的个人收藏的文件。
答案 4 :(得分:1)
实施它,然后测试它。如果它很慢,请仔细看看。
“过早优化是所有邪恶的根源。” - D. Knuth
另外:您不应该要求某些实现功能,特别是如果它们是黑盒子的话。如果您在以后用并发列表替换该列表会发生什么?如果Oracle决定重写List会怎样?还会快吗?你只是不知道。
答案 5 :(得分:0)
你不必担心这一点。列表实现跟踪大小。通话费用仅为O(1)。如果您非常好奇,可以阅读Collection的具体类的实现的源代码,并在那里查看size()方法。
答案 6 :(得分:0)
实现从私有预先计算的变量中获取它,因此它并不昂贵。
答案 7 :(得分:0)
答案 8 :(得分:0)
我认为LinkedList的某些实现会计算每次调用的总数。对方法本身的调用可能有点费力,但只有当我们讨论大型迭代或硬件的驱动程序编码时才真正成为问题。
在任何一种情况下,如果将其保存到局部变量,都不会有任何问题。