Java中使用foreach遍历list的盲点,

我们通常在项目中会用到ArrayList ,喜欢使用jdk1.5以后的foreach进行对list集合遍历,但是以下的操作会遇到小坑请看代码:

public class TestListUtils {
	public static void main(String[] args) {
		ArrayList<Student> a = new ArrayList<Student>();
		a.add(new Student(1, "zhao", true, 50.5, new Date()));
		a.add(new Student(2, "qian", false, 60.5, new Date()));
		a.add(new Student(3, "sun", true, 70.5, new Date()));
		a.add(new Student(4, "li", false, 80.5, new Date()));
		a.add(new Student(5, "zhou", true, 90.5, new Date()));
		a.add(new Student(6, "wu", true, 1000.5, new Date()));
		for (Student student : a) {
			System.out.println(student);
		}
		System.out.println("=======================================");
		ArrayList<Student> b = new ArrayList<Student>();
		b.add(new Student(3, "sun", true, 70.5, new Date()));
		b.add(new Student(4, "li", false, 80.5, new Date()));
		b.add(new Student(5, "zhou", true, 90.5, new Date()));
		for (Student student : b) {
			System.out.println(student);
		}
		for (Student student : a) {
			for (int i = 0; i < b.size(); i++) {
				a.remove(i);
			}
		}
	}
}
在代码中的双层循环中,我们都是使用foreach对list集合操作的,这样会报错,如下:
Student [id=1, name=zhao, sex=true, score=50.5, birth=Thu Mar 29 11:05:31 CST 2018]
Student [id=2, name=qian, sex=false, score=60.5, birth=Thu Mar 29 11:05:31 CST 2018]
Student [id=3, name=sun, sex=true, score=70.5, birth=Thu Mar 29 11:05:31 CST 2018]
Student [id=4, name=li, sex=false, score=80.5, birth=Thu Mar 29 11:05:31 CST 2018]
Student [id=5, name=zhou, sex=true, score=90.5, birth=Thu Mar 29 11:05:31 CST 2018]
Student [id=6, name=wu, sex=true, score=1000.5, birth=Thu Mar 29 11:05:31 CST 2018]
=======================================
Student [id=3, name=sun, sex=true, score=70.5, birth=Thu Mar 29 11:05:31 CST 2018]
Student [id=4, name=li, sex=false, score=80.5, birth=Thu Mar 29 11:05:31 CST 2018]
Student [id=5, name=zhou, sex=true, score=90.5, birth=Thu Mar 29 11:05:31 CST 2018]
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
	at java.util.ArrayList$Itr.next(Unknown Source)
	at test_cnbookingapi.TestListUtils.main(TestListUtils.java:36)

ArrayList的父类AbstarctList中有一个域modCount,每次对集合进行修改(增添元素,删除元素……)时都会modCount++而foreach的背后实现原理其实就是Iterator(关于Iterator可以看Java Design Pattern: Iterator),等同于注释部分代码。在这里,迭代ArrayList的Iterator中有一个变量expectedModCount,该变量会初始化和modCount相等,但如果接下来如果集合进行修改modCount改变,就会造成expectedModCount!=modCount,此时就会抛出java.util.ConcurrentModificationException异常。

解决办法:

1)在使用iterator迭代的时候使用synchronized或者Lock进行同步;

2)使用并发容器CopyOnWriteArrayList代替ArrayList和Vector。

不过我采用外层是for循环内层是foreach解决此问题:
public class TestListUtils {
	public static void main(String[] args) {
		ArrayList<Student> a = new ArrayList<Student>();
		a.add(new Student(1,"zhao",true,50.5,new Date()));
		a.add(new Student(2,"qian",false,60.5,new Date()));
		a.add(new Student(3,"sun",true,70.5,new Date()));
		a.add(new Student(4,"li",false,80.5,new Date()));
		a.add(new Student(5,"zhou",true,90.5,new Date()));
		a.add(new Student(6,"wu",true,1000.5,new Date()));
		for (Student student : a) {
			System.out.println(student);
		}
		System.out.println("=======================================");
		ArrayList<Student> b= new ArrayList<Student>();
			b.add(new Student(3,"sun",true,70.5,new Date()));
			b.add(new Student(4,"li",false,80.5,new Date()));
			b.add(new Student(5,"zhou",true,90.5,new Date()));
			for (Student student : b) {
				System.out.println(student);
			}
		//删除集a中的某个元素
		/*for (Student student : a) {
		for (int i = 0; i < b.size(); i++) {
			a.remove(i);
		}	
		}	*/
		for (int i = 0; i < a.size(); i++) {
			for (Student student : b) {
				a.remove(i);			
			}
		}
	}
}

详细的讲解可以参考此文章:https://www.jianshu.com/p/c5b52927a61a




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章