以下列出3种集合遍历方式
初始化集合
strings = new ArrayList<String>();
for (int i = 0; i < 5; i++) {
strings.add(String.valueOf(i));
}
1//jdk1.5中新增的 增强for循环
凡数组和实现Iterable接口的类都可以使用增强for循环。for (String s : strings) {
}
2//普通的for循环遍历
for (int i = 0; i < strings.size(); i++) {}
3//通过iterator迭代器循环
for (Iterator<String> s = strings.iterator(); s.hasNext();) {}
4同3
Iterator<String> it = strings.iterator();while (it.hasNext()) {
}
3,4可视为一种
前几天 在写程序的时候碰到java.util.ConcurrentModificationException问题 情况是这样的 :
我在集合遍历的时候 调用的remove()操作 结果抛出异常
对于以上3中遍历方式 情况又有所不同
remove(String s){
strings.remove(s);
}
对于1 3 4两种方式
1 for (String s : strings) {
remove(s);
}
3 for (Iterator<String> s = strings.iterator(); s.hasNext();) {
remove(s.next());
}
4 Iterator<String> it = strings.iterator();
while (it.hasNext()) {
remove(it.next());
}
抛出异常
通过张孝祥老师的jdk1.5高新技术视频 问题得以解决
1 3 4种可以视为通过迭代器来实现迭代
而itertor.hasnext()方法通过
观察源码
ArrayList的内部类Itr实现了Itertor接口
hasNext()方法通过判断 cursor和size是否相等来判断是否走到文件结尾
而next()方法每次都会使cursor递增一位
所以hasnext()不会报错
观察next()方法
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
next()方法先会调用checkFOrCoumodification()检测
可以看到在初始化itertor迭代器的expectedModCount=modCount
而add()和remove()等对集合内元素的操作都会使modCount数值发生变化
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
所以当使用Itertor迭代过程中 任何对集合元素的操作都会使next()方法抛出异常
而在第二种即普通for循环迭代中
因为没有调用next()方法 所用不会报错
当在for循环中 对集合元素进行了操作
因为每次循环都会调用for循环的条件语句 即 i<strings.size()
所以每次返回的size()不同 即迭代得到正确结果
-version1.0- 14.12.28
-version 2.0-15.1.26