目录
1、删除List
2、删除Set
3、删除Map
注意事项:
public class ListDemo {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
list.forEach(System.out::println);
for(String str : list) {
if ("李四".equals(str)) {
list.remove(str);
}
}
list.forEach(s -> {
System.out.println("第1次删除后:" + list);
});
}
}
以上代码运行会发生并发修改异常ConcurrentModificationException,正确的方式是:
public class ListExample {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
System.out.println(list);
// 方法1:迭代器遍历
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
String s = iterator.next();
if ("李四".equals(s)) {
iterator.remove();
}
}
System.out.println("第1次删除后:" + list);
// 方法2:使用集合的removeIf()方法
list.removeIf(new Predicate() {
@Override
public boolean test(String s) {
return "王五".equals(s);
}
});
System.out.println("第2次删除后:" + list);
}
}
同样,Set也不能通过foreach删除,否则发生异常
public class SetExample {
public static void main(String[] args) {
Set set = new HashSet<>();
set.add("张三");
set.add("李四");
set.add("王五");
System.out.println(set);
// 此处会发生并发修改异常
for(String str : set) {
if ("张三".equals(str)) {
set.remove(str);
}
}
System.out.println("第1次删除后:" + set);
set.removeIf("李四"::equals);
System.out.println("第2次删除后:" + set);
}
}
public static void main(String[] args) {
Map map = new HashMap();
map.put(1, "张三");
map.put(2, "李四");
map.put(3, "王五");
map.put(4, "赵六");
map.forEach((k, v) -> System.out.println(k + "," + v));
Iterator> iterator = map.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry entry = iterator.next();
Integer key = entry.getKey();
if (key == 1) {
iterator.remove();
}
}
System.out.println(map);
}
使用普通for循环删除list里面的元素会有bug,当删除一个元素时,list的长度会减1,被删除元素的后一个元素会向前移动,导致只删了一部分符合条件的元素。
public class ListExample {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("张三");
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
System.out.println("删除前:" + list);
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
if ("张三".equals(s)) {
list.remove(s);
}
}
System.out.println("删除后:" + list);
}
}
以上代码的运行结果为:
删除前:[张三, 张三, 李四, 王五, 赵六]
删除后:[张三, 李四, 王五, 赵六]
原因是:
第一轮循环,i = 0,会删除第一个张三,删除之后只剩四个元素[张三, 李四, 王五, 赵六]
第二轮循环,i = 1,从第二个元素(也就是“李四”)开始判断
以上代码可以简单的改成如下,每次都比较第一个元素
public class ListExample {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("张三");
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
System.out.println("删除前:" + list);
for (int i = 0; i < list.size(); i++) {
String s = list.get(0);
if ("张三".equals(s)) {
list.remove(s);
}
}
System.out.println("删除后:" + list);
}
}
事实上Collection的removeIf()方法的实现也是通过Iterator的romove()方法删除元素,源码如下:
default boolean removeIf(Predicate super E> filter) { Objects.requireNonNull(filter); boolean removed = false; final Iteratoreach = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; }
那有童鞋就要问了,foreach遍历删除会发生异常,为什么普通for循环就能正常运行呢?
因为foreach也会被编译成迭代器遍历的方式,只不过调用的是集合的remove()方法,没有调用迭代器的remove()导致的异常。
foreach编译前:
public static void main(String[] args) { Listlist = new ArrayList<>(); list.add("张三"); list.add("张三"); list.add("李四"); list.add("王五"); list.add("赵六"); System.out.println("删除前:" + list); for (String s : list) { if ("张三".equals(s)) { list.remove(s); } } System.out.println("删除后:" + list); }
foreach编译后:
public static void main(String[] args) { Listlist = new ArrayList(); list.add("张三"); list.add("张三"); list.add("李四"); list.add("王五"); list.add("赵六"); System.out.println("删除前:" + list); Iterator var2 = list.iterator(); while(var2.hasNext()) { String s = (String)var2.next(); if ("张三".equals(s)) { list.remove(s); } } System.out.println("删除后:" + list); }
如果还想更深入了解为什么会发生异常,可以参考文章Java集合的快速失败原则
使用迭代器的remove()方法删除就可以了