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; } }
数学真是伟大.