普通for循環語法:
1 for (int i = 0; i < integers.length; i++) { 2 System.out.println(intergers[i]); 3 }
foreach 循環語法:
1 for(Integer in : integers){ 2 System.out.println(in); 3 }
今天我們來比較一下兩種for循環對ArrayList和LinkList集合的循環性能比較。首先簡單的了解一下ArrayList和LinkList的區別:
ArrayList:ArrayList是采用數組的形式保存對象的,這種方式將對象放在連續的內存塊中,所以插入和刪除時比較麻煩,查詢比較方便。
LinkList:LinkList是將對象放在獨立的空間中,而且每個空間中還保存下一個空間的索引,也就是數據結構中的鏈表結構,插入和刪除比較方便,但是查找很麻煩,要從第一個開始遍歷。
下面是我測試的代碼:
1 package cn.migu.newportal.activity.service.activity; 2 3 import java.util.ArrayList; 4 import java.util.LinkedList; 5 import java.util.List; 6 7 /** 8 * 9 * @author 10 * @version C10 2017年11月30日 11 * @since SDP V300R003C10 12 */ 13 public class Test 14 { 15 public static void main(String[] args) 16 { 17 18 // 實例化arrayList 19 List<Integer> arrayList = new ArrayList<Integer>(); 20 // 實例化linkList 21 List<Integer> linkList = new LinkedList<Integer>(); 22 23 // 插入10萬條數據 24 for (int i = 0; i < 100000; i++) 25 { 26 arrayList.add(i); 27 linkList.add(i); 28 } 29 30 int array = 0; 31 // 用for循環arrayList 32 long arrayForStartTime = System.currentTimeMillis(); 33 for (int i = 0; i < arrayList.size(); i++) 34 { 35 array = arrayList.get(i); 36 } 37 long arrayForEndTime = System.currentTimeMillis(); 38 System.out.println("用for循環arrayList 10萬次花費時間:" + (arrayForEndTime - arrayForStartTime) + "毫秒"); 39 40 // 用foreach循環arrayList 41 long arrayForeachStartTime = System.currentTimeMillis(); 42 for (Integer in : arrayList) 43 { 44 array = in; 45 } 46 long arrayForeachEndTime = System.currentTimeMillis(); 47 System.out.println("用foreach循環arrayList 10萬次花費時間:" + (arrayForeachEndTime - arrayForeachStartTime) + "毫秒"); 48 49 // 用for循環linkList 50 long linkForStartTime = System.currentTimeMillis(); 51 int link = 0; 52 for (int i = 0; i < linkList.size(); i++) 53 { 54 link = linkList.get(i); 55 } 56 long linkForEndTime = System.currentTimeMillis(); 57 System.out.println("用for循環linkList 10萬次花費時間:" + (linkForEndTime - linkForStartTime) + "毫秒"); 58 59 // 用froeach循環linkList 60 long linkForeachStartTime = System.currentTimeMillis(); 61 for (Integer in : linkList) 62 { 63 link = in; 64 } 65 long linkForeachEndTime = System.currentTimeMillis(); 66 System.out.println("用foreach循環linkList 10萬次花費時間:" + (linkForeachEndTime - linkForeachStartTime) + "毫秒"); 67 } 68 }
循環10萬次的時候,控制台打印結果: (結果每次都會變,但求個平均值還是可以分析出結果的)
用for循環arrayList 10萬次花費時間:6毫秒
用foreach循環arrayList 10萬次花費時間:7毫秒
用for循環linkList 10萬次花費時間:20489毫秒
用foreach循環linkList 10萬次花費時間:8毫秒
可以看出,循環ArrayList時,普通for循環比foreach循環花費的時間要少一點;循環LinkList時,普通for循環比foreach循環花費的時間要多很多。
當我將循環次數提升到一百萬次的時候,循環ArrayList,普通for循環還是比foreach要快一點;但是普通for循環在循環LinkList時,程序直接卡死。
結論:需要循環數組結構的數據時,建議使用普通for循環,因為for循環采用下標訪問,對於數組結構的數據來說,采用下標訪問比較好。
需要循環鏈表結構的數據時,一定不要使用普通for循環,這種做法很糟糕,數據量大的時候有可能會導致系統崩潰。
網上參考一種代碼更緊湊的寫法:
實體Person類
1 package cn.migu.newportal.activity.service.activity; 2 3 /** 4 * 5 * @author 6 * @version C10 2017年11月30日 7 * @since SDP V300R003C10 8 */ 9 public class Person 10 { 11 private String a; 12 13 private int b; 14 15 public Person(String a, int b) 16 { 17 super(); 18 this.a = a; 19 this.b = b; 20 } 21 22 public String getA() 23 { 24 return a; 25 } 26 27 public void setA(String a) 28 { 29 this.a = a; 30 } 31 32 public int getB() 33 { 34 return b; 35 } 36 37 public void setB(int b) 38 { 39 this.b = b; 40 } 41 42 }
測試ArrayList的主程序:
1 package com.zhang.loop; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import java.util.LinkedList; 6 import java.util.List; 7 8 public class TestArrayList { 9 private static final int COUNT = 800000; 10 private static List<Person> persons = new ArrayList<Person>(); 11 12 public static void main(String[] args) { 13 init(); 14 System.out.println("for循環測試結果:"+testFor()); 15 System.out.println("foreach循環測試結果:"+testForeach()); 16 System.out.println("iterator循環測試結果:"+testIterator()); 17 } 18 19 //初始化集合 20 public static void init(){ 21 for (int i = 0; i <COUNT; i++) { 22 persons.add(new Person("第"+i+"個元素",i)); 23 } 24 } 25 //for循環便利集合 26 public static long testFor(){ 27 long start = System.nanoTime(); 28 Person p = null; 29 for (int i = 0; i < persons.size(); i++) { 30 p = persons.get(i); 31 } 32 return (System.nanoTime()-start)/1000; 33 } 34 //foreach循環便利集合 35 public static long testForeach(){ 36 long start = System.nanoTime(); 37 Person p = null; 38 for (Person person : persons) { 39 p = person; 40 } 41 return (System.nanoTime()-start)/1000; 42 } 43 //iterator循環便利集合 44 public static long testIterator(){ 45 long start = System.nanoTime(); 46 Person p = null; 47 Iterator<Person> itreator = persons.iterator(); 48 while(itreator.hasNext()){ 49 p = itreator.next(); 50 } 51 return (System.nanoTime()-start)/1000; 52 } 53 54 }
ArrayList測試結果:
測試LinkedList的主程序:
1 package com.zhang.loop; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import java.util.LinkedList; 6 import java.util.List; 7 8 public class TestArrayList { 9 private static final int COUNT = 8000; 10 private static List<Person> persons = new LinkedList<Person>(); 11 12 public static void main(String[] args) { 13 init(); 14 System.out.println("for循環測試結果:"+testFor()); 15 System.out.println("foreach循環測試結果:"+testForeach()); 16 System.out.println("iterator循環測試結果:"+testIterator()); 17 } 18 19 //初始化集合 20 public static void init(){ 21 for (int i = 0; i <COUNT; i++) { 22 persons.add(new Person("第"+i+"個元素",i)); 23 } 24 } 25 //for循環便利集合 26 public static long testFor(){ 27 long start = System.nanoTime(); 28 Person p = null; 29 for (int i = 0; i < persons.size(); i++) { 30 p = persons.get(i); 31 } 32 return (System.nanoTime()-start)/1000; 33 } 34 //foreach循環便利集合 35 public static long testForeach(){ 36 long start = System.nanoTime(); 37 Person p = null; 38 for (Person person : persons) { 39 p = person; 40 } 41 return (System.nanoTime()-start)/1000; 42 } 43 //iterator循環便利集合 44 public static long testIterator(){ 45 long start = System.nanoTime(); 46 Person p = null; 47 Iterator<Person> itreator = persons.iterator(); 48 while(itreator.hasNext()){ 49 p = itreator.next(); 50 } 51 return (System.nanoTime()-start)/1000; 52 } 53 54 }
LinkedList測試結果:
記錄的存取方式有兩種:
一種是順序存儲(數組,ArrayList..)可以根據其下標找到對應的記錄
另一種是鏈接存儲(LinkedList..)鏈接存儲(拿單鏈表為例)則必須找到其前一個記錄的位置才能夠找到本記錄。
根據以上可以得到的結果是:for循環便於訪問順序存儲的記錄,而foreach和迭代器便於訪問鏈接存儲。