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;
        }
    }

 

数学真是伟大.

 

posted @ 2019-02-22 18:01  随意的马蒂洛克  阅读(8321)  评论(0编辑  收藏  举报