集合遍历的时候删除元素的方法
集合遍历的时候删除元素的方法
在看阿里巴巴java开发手册时,有一条建议是这样的。
【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
反例:
1
2
3
4
5
6
7
8
9
10
11
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
for (Integer item : list) {
if (item == 3) {
list.remove(item);
}
}
说明:这个例子的执行结果会出乎大家的意料,那么试一下把”1”换成”2”,会是同样的结果吗?
此时程序会抛出并发修改异常: java.util.ConcurrentModificationException
我们将ArrayList 换成 LinkedList 后,结果也是一样的
使用对ArrayList索引遍历,并删除每个元素
1
2
3
4
5
6
7
8
9
10
11
12
13
ArrayList<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
System.out.println("befor: " + list.size());
for (int i = 0; i < list.size(); i++) {
list.remove(i);
}
for (String item : list) {
System.out.println(item);
}
System.out.println("after: " + list.size());
结果如下:
1
befor: 3222after: 1
此时我们再尝试使用map做同样的操作,可以看到map的几种遍历方法都不能正确的删除
1
2
3
4
5
6
7
8
9
10
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 1);
map.put(2, 2);
map.put(3, 3);
for (Integer integer : map.keySet()) {
map.remove(integer);
}
for (Map.Entry<Integer, Integer> item : map.entrySet()) {
map.remove(item.getKey());
}
正例:
1
2
3
4
5
6
7
Iterator<String> it = a.iterator();
while (it.hasNext()) {
String temp = it.next();
if (删除元素的条件) {
it.remove();
}
}
同样地,对于HashMap, 也采用迭代器的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 1);
map.put(2, 2);
map.put(3, 3);
Iterator<Map.Entry<Integer, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
if (iterator.next().getKey() == 2) {
iterator.remove();
}
}
map.forEach((k, v) -> {
System.out.println("key: " + k + " value: " + v);
});
可以得到如下结果:
1
2
key: 1 value: 1
key: 3 value: 3
本文由作者按照 CC BY 4.0 进行授权