java for和for each用法和效率

循环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就出问题啦。就是多线程不安全的问题。


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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值