总结以下:
1.若是只是遍历集合或者数组,用foreach好些,快些,由于for每遍历一次都要判断一下条件。
2.若是对集合中的值进行修改,就要用for循环了。其实foreach的内部原理其实也是Iterator,但它不能像Iteratorhtml
同样能够人为的控制,并且也不能调用iterator.remove();更不能使用下标来访问每一个元素,因此不能用于增长,java
删除等复杂的操做。数组
-----------------------------------------------------------------------------------------------------------
并发
关于for循环和foreach的区别,你真的知道,用了那么多年使用起来已经很熟悉了,可忽然问我讲讲这两的区别,一下还真把我给卡住了一下,ide
下面从源码的角度简单分析一下吧;url
for循环经过下标的方式,对集合中指定位置进行操做,每次遍历会执行判断条件 i<list.size(),知足则继续执行,执行完一次i++;
spa
[java] view plain copy.net
for(int i=0;i<list.size();i++) code
{ orm
System.out.println(i + ":" + list.get(i));
}
也就是说,即便在for循环中对list的元素remove和add也是能够的,由于添加或删除后list中元素个数变化,继续循环会再次判断i<list.size(); 也就是说list.size()值也发生了变化,因此
是可行的,具体操做以下代码
[java] view plain copy
for (int i = 0; i < list.size(); i++) {
if (i == 3) {
list.add("中间插入的一个字符串");
}
if (i == 5) {
{
list.remove(6);
}
}
System.out.println(i + ":" + list.get(i));
}
一样地,使用foreach遍历上述集合,注意foreach是C#中的写法,在Java中写法依然是for (int i : list)
写法for(String str : list)
查看文档可知,foreach除了能够遍历数组,还能够用于遍历全部实现了Iterable<T>接口的对象。
用普通for循环的方式模拟实现一个foreach,因为List实现了Iterable<T>,
过程以下:首先经过iterator()方法得到一个集合的迭代器,而后每次经过游标的形式依次判断是否有下一个元素,若是有经过 next()方法则能够取出。 注意:
执行完next()方法,游标向后移一位,只能后移,不能前进。
用传统for循环的方式模拟 加强for循环
和for循环的区别在于,它对索引的边界值只会计算一次。因此在foreach中对集合进行添加或删掉会致使错误,抛出异常java.util.ConcurrentModificationException
[java] view plain copy
private static void testForeachMethod(ArrayList<String> list) {
int count = 0; // 记录index
for (String str : list) {
System.out.println(str);
count++;
if (count == 3) {
// foreach中修改集合长度会抛出异常
// list.add("foreach中插入的ABC");
}
}
}
1.首先是调用iterator()方法得到一个集合迭代器
初始化时
expectedModCount记录修改后的个数,当迭代器能检测到expectedModCount是否有过修改
在建立迭代器以后,除非经过迭代器自身的 remove
或 add
方法从结构上对列表进行修改,不然在任什么时候间以任何方式对列表进行修改,迭代器都会抛出
ConcurrentModificationException
。所以,面对并发的修改,迭代器很快就会彻底失败,而不是冒着在未来某个不肯定时间发生任意不肯定行为的风险。
注意,迭代器的快速失败行为没法获得保证,由于通常来讲,不可能对是否出现不一样步并发修改作出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException
。
所以,为提升这类迭代器的正确性而编写一个依赖于此异常的程序是错误的作法:迭代器的快速失败行为应该仅用于检测 bug。