Java中使用foreach遍历list的盲点,
2018-03-29 11:35
211 查看
我们通常在项目中会用到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集合操作的,这样会报错,如下:
解决办法:
1)在使用iterator迭代的时候使用synchronized或者Lock进行同步;
2)使用并发容器CopyOnWriteArrayList代替ArrayList和Vector。不过我采用外层是for循环内层是foreach解决此问题:
详细的讲解可以参考此文章:https://www.jianshu.com/p/c5b52927a61a
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改变,就会造成
expectedMod 9811 Count!=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
相关文章推荐
- java 避免不同库使用left join查询速率低效 采用 sql 注入foreach 遍历list查询方式
- Java使用foreach遍历集合元素
- List<Map<String,Object>>使用Java代码遍历以获取String,Object的值
- Java_LIST使用方法和四种遍历arrayList方法
- PHP 使用list函数each函数遍历数组(实现foreach)解析
- Java使用foreach遍历集合元素
- 黄聪:C#使用能够foreach对hashtable、List遍历时“集合已修改;可能无法执行枚举操作。”错误
- List<Map<String,Object>>如何使用Java代码遍历以获取String,Object的值
- Spring MVC使用jstl 标签c:forEach 遍历输出双层嵌套List的数据
- 使用list.all(list1),如何在页面使用c:forEach遍历?
- Java学习之容器上(Collection接口常用方法,Iterator接口,使用foreach循环遍历Collection集合元素,Set集合通用知识(Hashset类,hashcode()与Lin
- JAVA数组的遍历,使用了新的遍历方法foreach
- 使用foreach,list来遍历数组
- java ArrayList与LinkedList 使用for,forearch,Iterator的遍历效率
- Java学习之容器上(Collection接口常用方法,Iterator接口,使用foreach循环遍历Collection集合元素,Set集合通用知识(Hashset类,hashcode()与LinkedHashSet类))
- Java中遍历数组使用foreach循环还是for循环?
- Java8使用lambda表达式写的一个List,Set,Map遍历工具类
- 使用迭代遍历元素Java LinkedList
- List<Map<String,Object>>使用Java代码遍历以获取String,Object的值
- Java使用foreach遍历集合元素