首頁 > 軟體

Java中遍歷集合的並行修改異常解決方案範例程式碼

2022-12-15 14:03:47

遍歷集合的刪除元素的問題

問題引出:

當我們遍歷集合從中找出某一批元素並刪除的時候, 可能出現一種並行修改異常問題。

哪些變數會存在這個問題?

迭代器遍歷集合且直接用集合刪除元素的時候可能出現, 例如下面程式碼就會報錯。

public static void main(String[] args) {
    Collection<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    // 刪除全部aaa元素
    Iterator<String> ite =  list.iterator();
    while (ite.hasNext()) {
        String item = ite.next();
        if ("aaa".equals(item)) {
            list.remove("aaa");
        }
    }
}

增強for迴圈遍歷集合且直接用集合刪除元素的時候可能出現, 例如下面程式碼同樣會報錯。

public static void main(String[] args) {
    Collection<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    for (String item : list) {
        if ("aaa".equals(item)) {
            list.remove("aaa");
        }
    }
}

Lambda方法遍歷同樣會出現一樣的bug

public static void main(String[] args) {
    Collection<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    list.forEach(s -> {
        if ("aaa".equals(s)) {
            list.remove("aaa");
        }
    });
}

使用for迴圈, 不會報錯, 但是刪除資料會出現問題, 例如下面程式碼中會漏刪aaa

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("aaa");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    for (int i = 0; i < list.size(); i++) {
        String item = list.get(i);
        if ("aaa".equals(item)) {
            list.remove("aaa");
        }
    }

    System.out.println(list); // [ccc, ddd, aaa]
}

解決方案:

迭代器的解決方法: 迭代器遍歷集合但是用迭代器自己的刪除方法操作可以解決。

public static void main(String[] args) {
    Collection<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    // 刪除全部aaa元素
    Iterator<String> ite =  list.iterator();
    while (ite.hasNext()) {
        String item = ite.next();
        if ("aaa".equals(item)) {
            // shiy 迭代器刪除方法, 刪除當前所在元素
            ite.remove();
        }
    }

    System.out.println(list); // [bbb, ccc, ddd]
}

for迴圈的解決方法一: 從後往前刪

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("aaa");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    for (int i = list.size() - 1; i >= 0; i--) {
        String item = list.get(i);
        if ("aaa".equals(item)) {
            list.remove("aaa");
        }
    }

    System.out.println(list); // [ccc, ddd]
}

for迴圈的解決方法二: 刪除完元素讓 i 減1, i--

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    list.add("aaa");
    list.add("aaa");
    list.add("ccc");
    list.add("aaa");
    list.add("ddd");
    list.add("aaa");

    for (int i = 0; i < list.size(); i++) {
        String item = list.get(i);
        if ("aaa".equals(item)) {
            list.remove("aaa");
            // 刪除了元素i--
            i--;
        }
    }

    System.out.println(list); // [ccc, ddd]
}

總結

到此這篇關於Java中遍歷集合的並行修改異常解決的文章就介紹到這了,更多相關Java遍歷集合並行修改異常內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com