栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

集合中元素删除

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

集合中元素删除

在Java中删除集合中元素时,需要特别注意,一方面是因为,Java是并发编程语言,如果存在并发操作,则会出现逻辑异常;另一方面,在List中删除元素,如果操作不当,则会抛出异常。
阿里推出的《Java开发手册》中的编程规范要求:不要在 foreach 循环里进行元素的 remove/add 操作。对应描述如下:

【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator
方式,如果并发操作,需要对 Iterator 对象加锁。  
正例: 
List list = new ArrayList<>(); 
list.add("1"); 
list.add("2"); 
Iterator iterator = list.iterator(); 
while (iterator.hasNext()) { 
    String item = iterator.next(); 
    if (删除元素的条件) { 
        iterator.remove(); 
    } 
} 
反例: 
for (String item : list) { 
    if ("1".equals(item)) { 
        list.remove(item); 
    } 
} 
说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的结果吗? 
Collection中删除元素

Collection中删除元素时,可以直接调用remove方法。但是,如果在forEach循环中删除元素,则会报错。错误示例如下:

public void removeElement() {
    List list = new LinkedList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    for (String item : list) {
        if ("1".equals(item)) {
            list.remove(item);
        }
    }
}

直觉上,上述代码不会有问题,就是在遍历List的时候,删除指定元素。但是,这种方法将会导致运行时异常。异常堆栈如下图所示。

查看异常堆栈,发现是执行checkForComodification校验时,抛出并发修改异常。对应代码如下:

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

也就是说,在forEach中增加或删除元素时,会进行并发修改校验。所以,不应在forEach中对Collection执行元素增加/删除操作。如果需要在forEach中增加或删除元素,可以使用Iterator,示例代码如下:

public void removeElement() {
    List list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    Iterator iterator = list.iterator();
    while (iterator.hasNext()) {
        String item = iterator.next();
        if ("1".equals(item)) {
            iterator.remove();
        }
    }
}

Java 8 以后,Collection新增removeIf用来实现循环中元素删除。示例代码如下:

public void removeElement() {
    List list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    list.removeIf(item -> "1".equals(item));
}

分析removeIf可知,其实现就是使用Iterator。源码如下:

default boolean removeIf(Predicate filter) {
    Objects.requireNonNull(filter);
    boolean removed = false;
    final Iterator each = iterator();
    while (each.hasNext()) {
        if (filter.test(each.next())) {
            each.remove();
            removed = true;
        }
    }
    return removed;
}

当然,也可使用java 8的Stream接口的filter方法来过滤并生成新Collection的方式,此处不再赘述,有兴趣的同学可以自行练习使用。

Map中删除元素

与Collection一样,在Map中删除元素时,可以直接调用remove方法。但是,如果在forEach循环中删除元素,则会报错。错误示例如下:

public void removeElement() {
    Map map = new HashMap<>();
    map.put("1", "1");
    map.put("2", "2");
    map.put("3", "3");
    map.entrySet().forEach(entry -> {
        if("1".equals(entry.getKey())){
            map.remove("1");
        }
    });
}

执行上述代码抛出的异常和使用forEach遍历并删除Collection中元素抛出异常一致,这里不再重复说明map中同样可以通过Iterator在Map中删除元素。示例代码如下:

public void removeMapElement() {
    Map map = new HashMap<>();
    map.put("1", "1");
    map.put("2", "2");
    map.put("3", "3");
    Iterator> it = map.entrySet().iterator();
    while(it.hasNext()){
        Map.Entry entry = it.next();
        if(entry.getKey() == "1") {
            it.remove();
        }
    }
}
参考

《Java开发手册》 嵩山版 阿里巴巴
https://blog.csdn.net/hu18315778112/article/details/124321602 List集合for循环删除元素
https://www.cnblogs.com/cchilei/p/13099203.html map循环删除某个元素

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/831919.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号