在百度了解了 List 的基本操作用法和遍历方法之后,开始测试遍历修改 List 的方法。

首先是基础的 for 遍历:

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("abc");
        list.add("123");
        list.add("efgh");
        list.add("456");
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).contains("123")) {
                String str = list.get(i);
                list.set(i, "1234");
            } else if (list.get(i).contains("efgh")) {
                list.set(i, "efg");
            }
        }
        System.out.println("list" + list);
    }
}

标准输出:

list[abc, 1234, efg, 456]

修改结果一切正常。

list.set(i, "1234"); 修改成 list.remove(i);(使用下标或者元素测试都可以删除元素),结果有点出乎意料:

list[abc, efgh, 456]

删除是正常删除掉了,但 efgh 修改失败了。

这还算好的,如果换成 foreach 写法,还会报错:

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("abc");
        list.add("123");
        list.add("efgh");
        list.add("456");
        for (String str:list) {
            if (str.contains("123")) {
                list.remove(list.indexOf(str));
            } else if (str.contains("efgh")) {
                list.set(list.indexOf(str), "efg");
            }
        }
        System.out.println("list" + list);
    }
}
Runtime Error (NZEC)

Exception in thread "main" java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1009)
    at java.base/java.util.ArrayList$Itr.next(ArrayList.java:963)
    at Main.main(Main.java:11)

此时尝试添加迭代器,或者复制一份,遍历 list 删除副本对应元素。

使用迭代器遍历 List

        List<String> list = new ArrayList<>();
        list.add("abc");
        list.add("123");
        list.add("efgh");
        list.add("456");
        Iterator<String> strIter = list.listIterator();
        while (strIter.hasNext()) {
            String str = strIter.next();
            if (str.contains("123")) {
                strIter.remove();
            
            } else if (str.contains("efgh")) {
                // strIter.set("efg");
            }
        }
        System.out.println("list" + list);

但是迭代器没有 set 修改方法,只能删除,pass。

使用 stream 的 forEach 方法遍历

        List<String> list = new ArrayList<>();
        list.add("abc");
        list.add("123");
        list.add("efgh");
        list.add("456");

        list.stream()
            .filter(str -> !Objects.equals(str, ""))
            .forEach(str -> {
                if (str.contains("123")) {
                    list.remove(str);

                } else if (str.contains("efgh")) {
                    list.set(list.indexOf(str), "efg");
                }
            });
        System.out.println("list" + list);

参考:从入门到精通:Java List遍历修改的完全指南 - jb51.net
遍历的同时修改一个 List 有几种方式?

文章目录