普通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和迭代器便于访问链接存储。