在日常Java 开发中,想要在遍历中删除一个集合中的元素,这是很常见的,但是如果用法不当,那么就会导致系统存在一些隐式bug ! 笔者今天拿list 举例来分析一下,Java 中集合应如何正确删除.
1. 错误删除方式示例:
1.1 在for each 循环体中遍历删除
-
-
-
- @Test(expected=java.util.ConcurrentModificationException.class)
- public void test_clear_error_1(){
- List<String> list = creatStringList();
- for (String str : list) {
- list.remove(str);
- }
- }
1.2. for 循环 正序遍历删除
-
-
-
-
- @Test
- public void test_clear_error_2(){
- List<String> list = creatStringList();
- for(int i=0; i<list.size(); i++){
- list.remove(i);
- }
- System.out.println(list);
- }
1.3. for 循环正序遍历删除2
-
-
-
- @Test(expected=java.lang.IndexOutOfBoundsException.class)
- public void test_clear_error_3(){
- List<String> list = creatStringList();
- int length = list.size();
- for(int i=0; i<length; i++){
- list.remove(i);
- }
- System.out.println(list);
- }
2. 正确删除方案
1. for 循环遍历删除
-
-
-
- @Test
- public void test_clear_right_1(){
- List<String> list = creatStringList();
- for(int i=list.size() -1 ; i>=0; i--){
- list.remove(i);
- }
- System.out.println(list);
- }
2. iterator 迭代删除
-
- @Test
- public void test_clear_right_2(){
- List<String> list = creatStringList();
- Iterator<String> iterator = list.iterator();
- while(iterator.hasNext()){
- iterator.remove();
- }
- System.out.println(list);
- }
3. removeAll 删除
-
-
-
-
- @Test
- public void test_clear_right_3(){
- List<String> list = creatStringList();
- list.removeAll(list);
- System.out.println(list);
- }
3. 总结
1. 在删除set , collection 时也是一样的,推荐使用倒序删除方法.
2. 在只需要删除一个元素的时候,for 循环正序删除也可以实现,但是在一次for 循环中删除多个的话,就会出现问题.所以建议在删除一个元素的时候,也使用倒序删除法.
如何正确遍历删除List中的元素,你会吗?
遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题。下面主要看看以下几种遍历删除List中元素的形式:
1.通过增强的for循环删除符合条件的多个元素
2.通过增强的for循环删除符合条件的一个元素
3.通过普通的for删除删除符合条件的多个元素
4.通过Iterator进行遍历删除符合条件的多个元素
-
-
-
-
- public void listRemove() {
- List<Student> students = this.getStudents();
- for (Student stu : students) {
- if (stu.getId() == 2)
- students.remove(stu);
- }
- }
-
-
-
- public void listRemoveBreak() {
- List<Student> students = this.getStudents();
- for (Student stu : students) {
- if (stu.getId() == 2) {
- students.remove(stu);
- break;
- }
- }
- }
-
-
-
-
-
-
-
-
-
- public void listRemove2() {
- List<Student> students = this.getStudents();
- for (int i=0; i<students.size(); i++) {
- if (students.get(i).getId()%3 == 0) {
- Student student = students.get(i);
- students.remove(student);
- }
- }
- }
-
-
-
- public void iteratorRemove() {
- List<Student> students = this.getStudents();
- System.out.println(students);
- Iterator<Student> stuIter = students.iterator();
- while (stuIter.hasNext()) {
- Student student = stuIter.next();
- if (student.getId() % 2 == 0)
- stuIter.remove();
- }
- System.out.println(students);
- }
for与foreach区别 参见
http://blog.csdn.net/heyuchang666/article/details/49683615
http://blog.csdn.net/u010031673/article/details/51800339
1、使用foreach来遍历集合时,集合必须实现Iterator接口,foreach就是使用Iterator接口来实现对集合的遍历的
2、
在用foreach循环遍历一个集合时不能向集合中增加元素,不能从集合中删除元素,否则会抛出ConcurrentModificationException异常。抛出该异常是因为在集合内部有一个
modCount变量用于记录集合中元素的个数,当向集合中增加或删除元素时,modCount也会随之变化,在遍历开始时会记录modCount的值,每次遍历元素时都会判断该变量是否发生了变化,如果发生了变化则抛出ConcurrentModificationException异常