1. 幾種遍歷方式及實現原理
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("測試1111");
list.add("測試2222");
list.add("測試3333");
System.out.println("----------for循環遍歷-----------");
//for循環遍歷
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
System.out.println(str);
}
System.out.println("-----------------iterator迭代器遍歷-----------");
//iterator迭代器遍歷
Iterator<String> it = list.iterator();
while(it.hasNext()){
String str = it.next();
System.out.println(str);
}
System.out.println("-------------foreach循環-------------------");
//foreach循環
for (Object o : list) {
System.out.println(o);
}
}
}
1.1 傳統的for循環遍歷,基於計數器的
遍歷者自己在集合外部維護一個計數器,然後依次讀取每一個位置的元素,當讀取到最後一個元素後,停止。主要就是需要按元素的位置來讀取元素
1.2 迭代器遍歷,Iterator
每一個具體實現的數據集合,一般都需要提供相應的Iterator。相比於傳統for循環,Iterator取締了顯式的遍歷計數器。所以基於順序存儲集合的Iterator可以直接按位置訪問數據。
而基於鏈式存儲集合的Iterator,正常的實現,都是需要保存當前遍歷的位置。然後根據當前位置來向前或者向後移動指針。
1.3 foreach循環遍歷
根據反編譯的字節碼可以發現,foreach內部也是採用了Iterator的方式實現,只不過Java編譯器幫我們生成了這些代碼
2. 不同遍歷方式的適用場合
2.1 傳統的for循環遍歷,基於計數器的
順序存儲:讀取性能比較高。適用於遍歷順序存儲集合。
鏈式存儲:時間複雜度太大,不適用於遍歷鏈式存儲的集合。
2.2 迭代器遍歷,Iterator
順序存儲:如果不是太在意時間,推薦選擇此方式,畢竟代碼更加簡潔,也防止了Off-By-One的問題。
鏈式存儲:意義就重大了,平均時間複雜度降爲O(n),還是挺誘人的,所以推薦此種遍歷方式。
2.3 foreach循環遍歷
foreach只是讓代碼更加簡潔了,但是他有一些缺點,就是遍歷過程中不能操作數據集合(刪除等),所以有些場合不使用。
而且它本身就是基於Iterator實現的,但是由於類型轉換的問題,所以會比直接使用Iterator慢一點,但是還好,時間複雜度都是一樣的
總結:具體的場合中應該要具體分析,根據具體的數據結構和對性能的要求來選擇不同的遍歷方式。