JAVA集合:for迴圈、foreach、迭代器效率比較
阿新 • • 發佈:2018-12-15
前言
寫程式碼的過程中,經常需要遍歷集合,選擇一個高效的遍歷方法非常重要,今天來看下for迴圈、foreach、迭代器效率比較,主要從ArrayList和LinkedList來分析。
直接上程式碼測試
ArrayList
List<Integer> integers = Lists.newArrayList(); for(int i=0;i<100000;i++){ integers.add(i); } long start1 = System.currentTimeMillis(); for(int count =0 ;count<10;count++){ for(int i=0;i<integers.size();i++){ int j=integers.get(i); } } System.out.println(String.format("for迴圈100次時間:%s ms",System.currentTimeMillis()-start1)); long start2 = System.currentTimeMillis(); for(int count =0 ;count<10;count++) { for (Integer i : integers) { int j = i; } } System.out.println(String.format("foreach迴圈100次時間:%s ms",System.currentTimeMillis()-start2)); long start3 = System.currentTimeMillis(); for(int count =0 ;count<10;count++) { Iterator<Integer> iterator = integers.iterator(); while(iterator.hasNext()){ int j=iterator.next(); } } System.out.println(String.format("迭代器迴圈100次時間:%s ms",System.currentTimeMillis()-start3));
結果:
for迴圈100次時間:15 ms
foreach迴圈100次時間:25 ms
迭代器迴圈100次時間:20 ms
ArrayList下三者效率差不多,for迴圈最優,因為ArrayList通過陣列來實現,陣列通過索引來定位的時間複雜度是O(1),1次就能定位到,所以效率非常高
LinkedList
List<Integer> integers = Lists.newLinkedList(); for(int i=0;i<100000;i++){ integers.add(i); } long start1 = System.currentTimeMillis(); for(int count =0 ;count<10;count++){ for(int i=0;i<integers.size();i++){ int j=integers.get(i); } } System.out.println(String.format("for迴圈100次時間:%s ms",System.currentTimeMillis()-start1)); long start2 = System.currentTimeMillis(); for(int count =0 ;count<10;count++) { for (Integer i : integers) { int j = i; } } System.out.println(String.format("foreach迴圈100次時間:%s ms",System.currentTimeMillis()-start2)); long start3 = System.currentTimeMillis(); for(int count =0 ;count<10;count++) { Iterator<Integer> iterator = integers.iterator(); while(iterator.hasNext()){ int j=iterator.next(); } } System.out.println(String.format("迭代器迴圈100次時間:%s ms",System.currentTimeMillis()-start3));
結果:
for迴圈100次時間:59729 ms
foreach迴圈100次時間:18 ms
迭代器迴圈100次時間:14 ms
可以看到for迴圈在LinkedList下效率特別低,我們來看下LinkedList的get做了什麼
Node<E> node(int index) { // assert isElementIndex(index); if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
get呼叫到node(index)方法,從程式碼可以看到,當index<size/2時從前往後找,否則從後往前找,使LinkedList的每個元素通過下標方式查詢最多查詢size/2次,因此遍歷100000個元素總共需要查詢的次數是size/2/2size = 100000100000/4,效率遠低於ArrayList通過下標直接定位,總共只需要查詢100000次,所以經常會說LinkedList的查詢效率低,ArrayList的查詢效率高,其實這裡指的是for迴圈通過下標查詢的角度,通過迭代器查詢的效率都很高,差不多。