循环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就出问题啦。就是多线程不安全的问题。
所以大家以后迭代集合的同时对集合操作一定要小心又小心, 不要以为没有抛异常就是没事!
而且在多线程并发的时候, 一个线程要迭代, 一个线程要对集合操作的时候, 抛不抛异常就要撞大运了!