循环ArrayList时,普通for循环比foreach循环花费的时间要少一点;

循环LinkedList时,普通for循环比foreach循环花费的时间要多很多。 

将循环次数提升到一百万次的时候,循环ArrayList,普通for循环还是比foreach要快一点;

但是普通for循环在循环LinkedList时,程序直接卡死。

原因:foreach使用的是迭代器

结论:需要循环数组结构的数据时,建议使用普通for循环,因为for循环采用下标访问,对于数组结构的数据来说,采用下标访问比较好。 

需要循环链表结构的数据时,需要使用迭代器的方式访问数据,效率会很高。当链表数据结构的数据量比较大时一定不要使用普通for循环,这种做法很糟糕,有可能会导致系统崩溃。

具体可以看如下举例:

数组遍历:for 遍历

public static void main(String[] args) {
 long[] array = new long[100000];
 for(int i = 0; i < array.length; i++){
 Random r = new Random();
 long tmp = r.nextLong();
 array[i] = tmp;
 }
 
 long time1 = System.currentTimeMillis();
 for(int i = 0; i < array.length; i++){
 System.out.println(array[i]);
 }
 long time2 = System.currentTimeMillis();
 System.out.println("for循环时间:" + (time2 - time1));
 }

for each 遍历

long time3 = System.currentTimeMillis();
for(long l : array){
 System.out.println(l);
}
long time4 = System.currentTimeMillis();
System.out.println("for each循环时间:" + (time4 - time3));

for循环时间:1399,for each循环时间:1455。多次执行2种遍历时间不相上下。效率相当。推荐使用for循环,它可以通过下标访问数组元素。

ArrayList 遍历 : for循环

public static void main(String[] args) {
 List<Long> array = new ArrayList<Long>();
 for(int i = 0; i < 100000; i++){
 Random r = new Random();
 long tmp = r.nextLong();
 array.add(tmp);
 }
 long time1 = System.currentTimeMillis();
 for(int i = 0; i < array.size(); i++){
 System.out.println(array.get(i));
 }
 long time2 = System.currentTimeMillis(); System.out.println("for循环时间:" + (time2 - time1));
}

for each循环

long time3 = System.currentTimeMillis();
for(long l : array){
 System.out.println(l);
}
long time4 = System.currentTimeMillis();System.out.println("for each循环时间:" + (time4 - time3));

for循环时间:1390,for each循环时间:1395。多次执行2种遍历时间不相上下。效率相当。

LinkedList遍历:

for循环

public static void main(String[] args) {
 List<Long> array = new LinkedList<Long>();
 for(int i = 0; i < 100000; i++){
 Random r = new Random();
 long tmp = r.nextLong();
 array.add(tmp);
 }
 
 long time1 = System.currentTimeMillis();
 for(int i = 0; i < array.size(); i++){
 System.out.println(array.get(i));
 }
 long time2 = System.currentTimeMillis();
 System.out.println("for循环时间:" + (time2 - time1));}

for each循环

long time3 = System.currentTimeMillis();
for(long l : array){
 System.out.println(l);
}
long time4 = System.currentTimeMillis();
System.out.println("for each循环时间:" + (time4 - time3));

for循环时间:20634, for each循环时间:1476。foreach节省大量时间,LinkedList遍历要求使用foreach。


使用for each循环语句的优势在于更加简洁,更不容易出错,不必关心下标的起始值和终止值。
forEach不是关键字,关键字还是for,语句是由iterator实现的,他们最大的不同之处就在于remove()方法上。
 
 一般调用删除和添加方法都是具体集合的方法,例如:
List list = new ArrayList(); list.add(...); list.remove(...);
但是,如果在for each循环的过程中调用集合的remove()方法,就会导致循环出错,
因为循环过程中list.size()的大小变化了,就导致了错误。 所以,如果想在循环语句中删除集合中的某个元素,
就要用迭代器iterator的remove()方法,因为它的remove()方法不仅会删除元素,还会维护一个标志,
用来记录目前是不是可删除状态,这就涉及到源码了,想考虑了可以看下是否报Java ConcurrentModificationException异常报错,有2个可能:
一种是,在for each循环的时候改变了list集合的大小。
二是,在多线程下操作一个集合,在修改集合位置的时候,同时又循环list就出问题啦。就是多线程不安全的问题。


所以大家以后迭代集合的同时对集合操作一定要小心又小心, 不要以为没有抛异常就是没事!
而且在多线程并发的时候, 一个线程要迭代, 一个线程要对集合操作的时候,  抛不抛异常就要撞大运了!