2013-02-23 35 views
2

我知道,通過一個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

回答

3

這是否有像使用迭代器一樣的性能?

是的。這兩種變體都會生成相同的字節碼。從換每個循環產生以下的字節碼,但在循環使用迭代器時,它看起來完全一樣:

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

2

foreach循環使用Iterable接口。它調用iterator()並迭代迭代器。 數組使用特殊處理。

0

一個不同之處在於,當您不想更改列表的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