的差异循环访问链表
我知道,通过一个LinkedList使用迭代的差异循环访问链表
for(int i = 0; i < list.size(); i++){
Item item = list.get(i);
}
来从列表达开始的单个对象有坏性能。获得的每次调用(我)迭代一世。
正确的方法是使用迭代器。到现在为止还挺好。
可是你知道这种风格:
for(Item item : list){
// item is already here
}
这是否有像使用迭代器相同的性能?这是如何在内部工作的?
这是否有像使用迭代器一样的性能?
是的。这两种变体都会生成相同的字节码。从换每个循环产生以下的字节码,但在循环使用迭代器时,它看起来完全一样:
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 Loop和How does the Java 'for each' loop work?以获取一些其他信息。
非常感谢!这正是我想知道的:) – 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
对'size()'的调用并不是传统'for'循环中使用'LinkedList'的低效部分,而是'get(i)'调用使其变慢。 'get(i)'在每次调用时都会从第一个内部迭代到'i',而迭代器会记住它是当前位置,并在单个步骤中进入下一个元素。 – jlordo 2013-02-23 19:29:37
雅这是真的,但我只谈论一般的差异。 – Arpit 2013-02-23 19:32:11
OP的问题显然是关于'LinkedList'。一般的'List'答案似乎没有帮助。由于LinkedList是如何实现的,因此使用常量值而不是size()来获得相同性能的说法显然是错误的。 – jlordo 2013-02-23 19:34:44
您可以实现一个LinkedList w这个使用老式循环和list.get(i)没有不好的表现。简单地缓存最后访问的节点,希望下一个呼叫是列表中直接跟随的节点。这会导致与任何迭代器使用类似的性能。 – MrSmith42 2013-02-23 19:23:09
可能重复[每个循环的Java如何工作?](http://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work) – 2013-02-23 19:34:35