list 集合addAll 和 add 方法小坑


1.問題

我們經常會遍歷 list集合,在遍歷的過程中,如果在遍歷的過程中添加了 add()  或者 addAll() 方法修改了遍歷的list列表,那么會報錯.

代碼演示:

        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        for(int i = 0;i<list.size();i++){
            System.out.println(i);
        }

這段代碼的結果大家都知道, 0  1  2;

但是如果在遍歷的過程中修改了list 的內容

        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        for(int i = 0;i<list.size();i++){
            System.out.println(i);
            list.add(4);
        }

那么就會出現死循環,原因是list實現是數組,list.size() 在add之后 size() 會增加,也就是說 list的下標一直在增加, list.size()的值也一直在增加,所以出現了死循環.addAll()方法同理

而且jdk文檔也已經說明了這一點:

添加指定 collection 中的所有元素到此列表的結尾,順序是指定 collection 的迭代器返回這些元素的順序(可選操作)。如果在操作正在進行中修改了指定的 collection,那么此操作的行為是不確定的(注意,如果指定的 collection 是此列表,並且它是非空的,則會發生這種情況。)

2.解決:

創建一個臨時list變量就可以解決.

        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        List<Object> temp =  Arrays.asList(list.toArray());
        for(int i = 0;i<temp.size();i++){
            System.out.println(i);
            list.add(4);
        }

如圖,在遍歷前創建一個temp變量即可. 注意:因為toArray()方法返回的是Object類型,所以只能創建List<Object>,大家有更好的解決可以和我交流交流.

附上剛剛完成的代碼,用遞歸實現遍歷樹狀圖;

    //遞歸獲取架構下級id
    private static  List<Integer> selectAllStructLowLevelIdById(List<Integer> list) {
        if(list == null || list.isEmpty()){
            return list;
        }else{
            //創建臨時變量,用來遍歷
            List<Object> template = Arrays.asList(list.toArray());
            
            for(int i = 0;i<template.size();i++){
                List<Integer> ids = attendanceMapper.selectStructLowLevelIdById((Integer)template.get(i));
                list.addAll(selectAllStructLowLevelIdById(ids));
            }
            return list;
        }
    }

 

數學真是偉大.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM