的差异循环访问链表

问题描述:

我知道,通过一个LinkedList使用迭代的差异循环访问链表

for(int i = 0; i < list.size(); i++){ 
    Item item = list.get(i); 
} 

来从列表达开始的单个对象有坏性能。获得的每次调用(我)迭代一世。

正确的方法是使用迭代器。到现在为止还挺好。

可是你知道这种风格:

for(Item item : list){ 
    // item is already here 
} 

这是否有像使用迭代器相同的性能?这是如何在内部工作的?

+0

您可以实现一个LinkedList w这个使用老式循环和list.get(i)没有不好的表现。简单地缓存最后访问的节点,希望下一个呼叫是列表中直接跟随的节点。这会导致与任何迭代器使用类似的性能。 – MrSmith42 2013-02-23 19:23:09

+0

可能重复[每个循环的Java如何工作?](http://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work) – 2013-02-23 19:34:35

这是否有像使用迭代器一样的性能?

是的。这两种变体都会生成相同的字节码。从换每个循环产生以下的字节码,但在循环使用迭代器时,它看起来完全一样:

for(Object o : list) { 
} 

    44: aload_1 
    45: invokevirtual #30     // Method java/util/LinkedList.iterator:()Ljava/util/Iterator; 
    48: astore_3 
    49: goto   59 
    52: aload_3 
    53: invokeinterface #34, 1   // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object; 
    58: astore_2 
    59: aload_3 
    60: invokeinterface #40, 1   // InterfaceMethod java/util/Iterator.hasNext:()Z 
    65: ifne   52 

内部是怎样工作的呢?

如果是非数组,则for-each-loop在内部使用迭代器。看到上面的字节代码 - 所有的方法都被调用,在使用迭代器时也会调用这些方法。

另请参阅The For-Each LoopHow does the Java 'for each' loop work?以获取一些其他信息。

+0

非常感谢!这正是我想知道的:) – Smashnet 2013-02-23 20:21:11

foreach循环使用Iterable接口。它调用iterator()并迭代迭代器。 数组使用特殊处理。

一个不同之处在于,当您不想更改列表的size时,将使用每个循环。因为它使用的iterators在列表的resize之后变成invalidate。而在正常情况下它不是一个循环的情况。但是standard loop每次调用size函数使得它的效率较低,然后for each。为了获得相同的性能,您需要将constant的值设为10,15,..等,条件为standard loop

  • 对于每个 - 只读模式

  • 标准为 - 读写两个

具体到这样一个问题:for循环的标准真的是低效的,因为你必须遍历该列表每次从头开始调用get.这是更大的问题然后拨打size

+0

对'size()'的调用并不是传统'for'循环中使用'LinkedList'的低效部分,而是'get(i)'调用使其变慢。 'get(i)'在每次调用时都会从第一个内部迭代到'i',而迭代器会记住它是当前位置,并在单个步骤中进入下一个元素。 – jlordo 2013-02-23 19:29:37

+0

雅这是真的,但我只谈论一般的差异。 – Arpit 2013-02-23 19:32:11

+0

OP的问题显然是关于'LinkedList'。一般的'List'答案似乎没有帮助。由于LinkedList是如何实现的,因此使用常量值而不是size()来获得相同性能的说法显然是错误的。 – jlordo 2013-02-23 19:34:44