簡體   English   中英

性能:通過Java中的List進行迭代

[英]Performance: Iterating through a List in Java

在Java中迭代遍歷列表是否更慢:

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

而不是:

for (Object o: list) {
    ... o
}

我假設你出於純粹的好奇心而不會引用Knuth(有人可能會這樣)。

我相信一旦你的代碼被編譯,它就沒有什么區別。 之前 確實有所不同(示例2更具可讀性和簡潔性),所以請選擇2號而不關心其余部分。

只需2美分

編輯

請注意,每次循環運行時,您在第1個代碼段中的代碼計算list.size() ,這可能會比第2個更慢

再來一次編輯

我不得不仔細檢查,Joshua Bloch建議for each循環使用(參見Effective Java 46項)。 我認為這結束了各種討論。 謝謝Josh! :)

普通列表的性能不應有任何明顯差異。

對於鏈表,迭代器將大大加快,特別是對於大型列表。

為這個問題創建了一個微基准測試 ,並且驚訝地發現 - 每次運行比索引循環快2x-3x。 我唯一的解釋是for-each版本可能不需要由ArrayList.get(int index)進行范圍檢查。

對於非常小的列表(10個元素),結果大致相同。 對於100個元素 - 每個元素快1.5倍,對於10000-100000個元素,速度快2倍-3倍。

測試在隨機數據集上運行,並且最后驗證校驗和,因此在這些中不太可能發生JIT。

根據While循環中的基准測試,For循環和Iterator性能測試 - Java和JavaRanch問題“ 正在使用ArrayList.iterator()比在循環中循環ArrayList更快嗎? ”迭代器實際上有點慢。

我仍然喜歡可讀性,除非我對我的整個應用程序進行基准測試,並發現循環是我的瓶頸。

不。當列表也實現時,速度更快(或者應該更快): RandomAccess (如ArrayList所做,而LinkedList則不然)。

但是,你應該總是使用后者:

 for( Object o: list ) {
 }

如果您有充分的證據表明您使用它有性能問題(例如,您對應用程序進行了分析,結果您認為這部分代碼的改進點),那么只能切換到前者。

如果你的應用程序需要它,你就有可能無法在以后的重構中切換你的實現(因為你將被綁定到for( int i = 0 ; i < list.size(); i++ ) idiom) 。

可能有所不同。

如果List實現也實現了java.util.RandomAccess(就像ArrayList那樣),那么在Interator上使用它的get()方法要快得多。

如果它沒有實現java.util.RandomAccess(例如,LinkedList沒有),那么使用迭代器要快得多。

但是,這僅限於使用包含數千個(可能是分散的)對象的列表或者經常遍歷的列表(就像在表示數字向量的List對象上執行大量數學運算一樣。)

檢查每次迭代的大小確實會增加i操作,但這對性能沒有太大影響。

通過這個,我的意思是兩者之間存在細微差別

int lsize = myList.size();
for(int i=0; i < lsize; i++)
{
   Object o = myList.get(i);
}

與:

for(int i=0; i < myList.size(); i++)
{
   Object o = myList.get(i);
}

但它基本上沒關系。 除了其他原因之外,請使用問題中的第二個來提高可讀性。

人們認識到隨機和順序*訪問之間的區別通常是模糊的。 例如,某些List實現*提供漸近線性訪問時間,如果它們變大,但實際上是恆定的訪問時間。 這樣的List實現*通常應該實現這個接口。 根據經驗,* List實現應實現此接口if,*對於類的典型實例,此循環:*

*     for (int i=0, n=list.size(); i < n; i++)
 *         list.get(i);
 *
*比這個循環運行得更快:*
\n  * for(Iterator i = list.iterator(); i.hasNext();)\n  * i.next();\n  * 
*

我沒有看到所有List實現的get()代碼,所以也許我會寫的是一些FUD。 我學到的是在for循環中使用get(i)將導致在每個循環運行中反復遍歷整個列表。 使用迭代器(如增強for for循環)只會將迭代器移動到下一個列表元素,而無需再次迭代整個列表。

我的結論是使用迭代器或增強的for循環應該更高效,因為使用get()將導致復雜度O(n^2)而不是O(n)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM