哪个表现更好:对于链表中的每个或迭代器?

时间:2014-09-10 09:56:21

标签: java collections foreach linked-list iterator

通过程序遍历LinkedList时,我一直在检查每个 vs 迭代器的效果:

public class ListTraversePerformance {
    public static void main(String... args){
        List<String> list = new LinkedList<String>();
        for(int i=0;i<100000;i++){
            list.add("Any String" + i);
        }
        Iterator i = list.iterator();
        String x;
        long t1 = System.currentTimeMillis();
        for(String j: list){
             x = j;

        }
        long t2 = System.currentTimeMillis();
        while(i.hasNext()){ 
            x= (String)i.next();

        }
        long t3 = System.currentTimeMillis();
        System.out.print((t2-t1) + "  " + (t3-t2));
    }
}

我得到的输出每次都不同,即有时第一个循环快速运行,有时第二个循环。

我的问题:

我认为每个循环的应该比第二个 Iterator 慢。我认为在for each循环中,每次复制O(n^2)O(n) Iterator的复杂性相比,链表应该从头开始遍历。我对么?如果是,那么为什么结果不像我期望的那样......

1 个答案:

答案 0 :(得分:3)

两者几乎相同,并且它们都是O(n),因为每个元素只被迭代一次。不重复迭代。

每个循环使用引擎盖下的迭代器。它是用于迭代实现Iterable的对象的语法糖,后者又创建了一个迭代器。因此,当我说两者几乎相同时,我的意思是字面意思。

微观基准测试很难做到正确。最大的问题是,我们最终认为我们正在计划一件事,但实际上我们正在计划其他事情;为了理解真正发生的事情,需要花费大量的精力去挖掘它们。阅读以下相关文章的答案,它将解释为什么时间变化如此之多以及如何使用它。 Why are floating point operations much faster with a warmup phase?。这个问题的SO与基于自己的基准测试几乎相同,只使用浮点运算而不是列表迭代。

快速摘要是1)JVM通过解释器开始执行代码,并动态优化代码的热区域,2)GC和其他后台进程可能会干扰,有些可能在JVM中,有些可能在外部JVM。