Why is list.size()>0 slower than list.isEmpty() in Java?
为什么
当我查看
ArrayList.size()
1 2 3 4 5 6 7 8 | /** * Returns the number of elements in this list. * * @return the number of elements in this list */ public int size() { return size; } |
ArrayList.isEmpty()
1 2 3 4 5 6 7 8 | /** * Returns <tt>true</tt> if this list contains no elements. * * @return <tt>true</tt> if this list contains no elements */ public boolean isEmpty() { return size == 0; } |
如果我们只编写一个简单的程序来获取这两种方法所花费的时间,那么在所有情况下,这种情况
这是我的TestCode;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import java.util.List; import java.util.Vector; public class Main { public static void main(String[] args) { List l=new Vector(); int i=0; for(i=0;i<10000;i++){ l.add(new Integer(i).toString()); } System.out.println(i); Long sTime=System.nanoTime(); l.size(); Long eTime=System.nanoTime(); l.isEmpty(); Long eeTime=System.nanoTime(); System.out.println(eTime-sTime); System.out.println(eeTime-eTime); } } |
在所有情况下为
对于
例如,对于
因此,如果您完全知道该列表是
*我最初是在这里写LinkedList的,它隐式地引用了
您的测试代码有缺陷。
只需颠倒顺序,即先调用isEmpty,然后调用size> 0秒,您将得到相反的结果。这是由于类加载,缓存等引起的。
很抱歉,您的基准测试存在缺陷。看看Java理论和实践:一个有缺陷的微基准的剖析,以获取有关如何接近基准的一般描述。
更新:要获得适当的基准,您应该研究Japex。
.size()必须查看整个列表,而.isEmpty()可以停在第一个列表上。
显然依赖于实现,但是正如前面已经说过的,如果您不需要知道实际大小,为什么还要麻烦计算所有元素?
您说过:
Here
eTime-sTime>eeTime-eTime in all cases Why?
首先,可能是因为您的测试代码。您无法同时测试调用l.size()和l.isEmpty()的速度,因为它们都查询相同的值。很有可能调用l.size()已将列表的大小加载到cpu缓存中,因此调用l.isEmpty()的速度要快得多。
您可以尝试在两个单独的程序中分别调用l.size()一百万次和l.isEmpty()数百万次,但是理论上编译器可以优化所有这些调用,因为您实际上并没有对结果做任何事情。
在任何情况下,两者之间的性能差异都可以忽略不计,尤其是进行比较后,您需要查看列表是否为空(
edit:我自己进行了测试。这几乎是一个折腾。在
这里要带走的事情是,当您尝试优化执行时间相差几纳秒的方法调用时,那么您做错了。首先正确掌握基础知识,例如在应该使用
鉴于这两个实现,速度应该相同,这是真的。
但是,到目前为止,这些方法并不是唯一可行的方法。例如,原始链表(不单独存储大小)可以比
更重要的是:
根据PMD(基于静态规则集的Java源代码分析器),isEmpty()是首选。
您可以在此处找到PMD规则集。搜索" UseCollectionIsEmpty"规则。
http://pmd.sourceforge.net/rules/design.html
根据我的说法,这还有助于使整个源代码保持一致,而不是使一半的人使用isEmpty(),其余的人使用size()==0。
对链接列表中的项目进行计数可能会非常缓慢。
通常不能说哪个更快,因为这取决于您使用的接口
假设我们正在谈论
1 2 3 4 5 6 7 | public boolean isEmpty() { return size == 0; } public int size() { return size; } |
您可以轻松地看到两个表达式
如果您对接口