總結以下:
1.若是隻是遍歷集合或者數組,用foreach好些,快些,由於for每遍歷一次都要判斷一下條件。
2.若是對集合中的值進行修改,就要用for循環了。其實foreach的內部原理其實也是Iterator,但它不能像Iteratorhtml
同樣能夠人爲的控制,並且也不能調用iterator.remove();更不能使用下標來訪問每一個元素,因此不能用於增長,java
刪除等複雜的操做。數組
-----------------------------------------------------------------------------------------------------------
併發
關於for循環和foreach的區別,你真的知道,用了那麼多年使用起來已經很熟悉了,可忽然問我講講這兩的區別,一下還真把我給卡住了一下,ide
下面從源碼的角度簡單分析一下吧;url
for循環經過下標的方式,對集合中指定位置進行操做,每次遍歷會執行判斷條件 i<list.size(),知足則繼續執行,執行完一次i++;
spa
[java] view plain copy.net
for(int i=0;i<list.size();i++) code
{ orm
System.out.println(i + ":" + list.get(i));
}
也就是說,即便在for循環中對list的元素remove和add也是能夠的,由於添加或刪除後list中元素個數變化,繼續循環會再次判斷i<list.size(); 也就是說list.size()值也發生了變化,因此
是可行的,具體操做以下代碼
[java] view plain copy
for (int i = 0; i < list.size(); i++) {
if (i == 3) {
list.add("中間插入的一個字符串");
}
if (i == 5) {
{
list.remove(6);
}
}
System.out.println(i + ":" + list.get(i));
}
一樣地,使用foreach遍歷上述集合,注意foreach是C#中的寫法,在Java中寫法依然是for (int i : list)
寫法for(String str : list)
查看文檔可知,foreach除了能夠遍歷數組,還能夠用於遍歷全部實現了Iterable<T>接口的對象。
用普通for循環的方式模擬實現一個foreach,因爲List實現了Iterable<T>,
過程以下:首先經過iterator()方法得到一個集合的迭代器,而後每次經過遊標的形式依次判斷是否有下一個元素,若是有經過 next()方法則能夠取出。 注意:
執行完next()方法,遊標向後移一位,只能後移,不能前進。
用傳統for循環的方式模擬 加強for循環
和for循環的區別在於,它對索引的邊界值只會計算一次。因此在foreach中對集合進行添加或刪掉會致使錯誤,拋出異常java.util.ConcurrentModificationException
[java] view plain copy
private static void testForeachMethod(ArrayList<String> list) {
int count = 0; // 記錄index
for (String str : list) {
System.out.println(str);
count++;
if (count == 3) {
// foreach中修改集合長度會拋出異常
// list.add("foreach中插入的ABC");
}
}
}
1.首先是調用iterator()方法得到一個集合迭代器
初始化時
expectedModCount記錄修改後的個數,當迭代器能檢測到expectedModCount是否有過修改
在建立迭代器以後,除非經過迭代器自身的 remove
或 add
方法從結構上對列表進行修改,不然在任什麼時候間以任何方式對列表進行修改,迭代器都會拋出
ConcurrentModificationException
。所以,面對併發的修改,迭代器很快就會徹底失敗,而不是冒着在未來某個不肯定時間發生任意不肯定行爲的風險。
注意,迭代器的快速失敗行爲沒法獲得保證,由於通常來講,不可能對是否出現不一樣步併發修改作出任何硬性保證。快速失敗迭代器會盡最大努力拋出 ConcurrentModificationException
。
所以,爲提升這類迭代器的正確性而編寫一個依賴於此異常的程序是錯誤的作法:迭代器的快速失敗行爲應該僅用於檢測 bug。