一、几种常见的遍历方式
1、普通for循环

2、高级for循环

3、iterator和removeIf

4、stream()

5、复制

6、普通for循环 --> 倒序方式

二、源码篇
1、普通for循环出错原因
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*

  • Private remove method that skips bounds checking and does not
  • return the value removed.
    */
    private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
    //remove会导致之后的元素往前移动,而下标不改变时就会出现bug
    System.arraycopy(elementData, index+1, elementData, index,
    numMoved);
    elementData[–size] = null; // clear to let GC do its work
    }
    我们在删除某个元素后,list的大小发生了变化,这时候你的的索引也会发生变化,这时就会导致你在遍历的时候漏掉某些元素。
    比如当你删除第1个元素后,我们如果还是继续根据索引访问第2个元素时,因为删除的关系,后面的元素都往前移动了一位,所以实际访问的是第3个元素。
    所以这种方式可以用在删除特定的一个元素时使用,但不适合循环删除多个元素时使用。

2、高级for循环出错原因
foreach其实是用迭代器来进行遍历的,而在遍历时直接使用arraylist的remove方法会导致什么问题呢?

可以再看一下fastremove和迭代器遍历的内部代码:

最后导致抛出上面异常的其实就是这个,简单说,调用list.remove()方法导致modCount和expectedModCount的值不一致而报异常

final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
//调用next时会调用checkForComodification方法检查 这两个字段
//而fastRemove里面只对modCount 进行了改变 导致抛出异常
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
所以遍历时remove并不适用于foreach。

3、java8中新方法removeIf
//内部其实就是迭代器遍历
default boolean removeIf(Predicate<? super E> 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;
}
和迭代器差不多,内部实现也是迭代器。

三、总结
1、在不考虑内存大小会不会出现OOM的时候,采取复制一个新的list的方法速度更快,适用于集合中对象不算多的时候,毕竟只需要add操作。

2、当集合中元素过多时,复制list就显得有些笨重了,采用迭代器的方式进行遍历较快一些,并且不用关注小角标的变化。

3、不考虑性能的时候使用removeIf方法,代码简洁明了。

4、当要针对角标进行元素的remove时,使用倒序遍历的方式最为妥当。
————————————————
版权声明:本文为CSDN博主「GooReey」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/guorui_java/article/details/110098348

List遍历删除元素remove()相关推荐

  1. java中List遍历删除元素

    删除末尾几个元素 import java.util.LinkedList; import java.util.List;public class TestList {public static voi ...

  2. java中List遍历删除元素,Android进阶之光

    一.结缘 实话说,最开始刷题的时候,刷的是 LeetCode,后来才注意到了剑指 offer 的存在,最开始也是听别人说的,剑指 offer 在面试过程中出现的概率很大,就去尝试将其都做了一遍,做的过 ...

  3. STL中用erase()方法遍历删除元素

    STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector .deque):另一类是以不连续的节点形式存储的容器(如:list.set.map).在使用erase方法来删除元素时 ...

  4. jQuery删除元素---remove()与empty()

    jQuery删除元素-remove()与empty() remove() - 删除被选元素(及其子元素) empty() - 从被选元素中删除子元素 举例:remove() <script> ...

  5. java list 遍历 删除元素_java中List遍历删除元素相关做法和注意事项

    首先,使用简单的for循环时,list.remove()肯定是没问题的,只要注意一下下标别越界就行. 示例代码: List ll = new ArrayList(); ll.add("1&q ...

  6. arraylist删除指定元素_【追凶】ArrayList使用增强for遍历删除元素异常ConcurrentModification...

    在工作中我们经常需要在遍历集合的时候删除元素,一开始我也以为只要在增强for循环中remove元素就可以了,现实给了我一个巴掌那就是ConcurrentModificationException. 首 ...

  7. Java 集合中遍历删除元素抛异常的原因,从ArrayList说起

    文章目录 使用for删除遗漏元素的原因: 使用foreach删除报错的原因: 其它集合的删除方法 删除集合元素的工具类 ArrayList删除元素的方式. 使用for循环删除.会遗漏删除的元素 使用f ...

  8. java set遍历删除元素_java中循环遍历删除List和Set集合中元素的方法

    今天在做项目时,需要删除List和Set中的某些元素,当时使用边遍历,边删除的方法,却报了以下异常: ConcurrentModificationException 为了以后不忘记,使用烂笔头把它记录 ...

  9. c++ vector删除元素remove与erase区别

    目录 erase: remove: vector中, remove函数和 erase函数都可以实现元素的删除,但它们的用法稍微有些区别: erase是删除指定位置的元素或者指定区域内的所有元素 rem ...

最新文章

  1. linux 后台运行jar包命令,Linux 运行jar包命令(Cent OS 7后台运行jar包)
  2. Oracle初始化参数含义
  3. yii2.0错误:Exception yii\base\InvalidConfigException with message
  4. 三星手机 java_如何在三星手机上安装Java ME应用程序?
  5. 爱了!蚂蚁开源的“SpringBoot”框架,新增了这6项功能...
  6. 基于Docker快速搭建ELK
  7. Excel-VBA操作文件四大方法之三(3/4)
  8. Python帮助文档的查看方式——Python初学者必看
  9. 含有一个量词的命题的否命题_第三节:简单的逻辑联结词、全称量词与存在量词...
  10. 毕业论文开题报告撰写指南-宾夕法尼亚州立大学研究生写作中心
  11. 史上最清晰的雷霆战机游戏开发全过程(基于java,素材和源码均齐全)
  12. Ubuntu 安装package提示依赖: XXX 但是它将不会被安装 解决方法
  13. Android黄油刀插件使用记录
  14. Oracle 基本SQL语句
  15. Win10 出现恢复,无法加载操作系统,关键系统驱动程序丢失或错误 蓝屏错误代码0xc000007b
  16. 初学者の发送QQ邮箱完整代码
  17. QT学习之路-资料收藏集锦
  18. 第十四章 涅焚心经的强大之处
  19. 清洁机器人--音频方案之基于国民MCU IO控制的唯创WT588 语音播放方案
  20. C++11 decltype 的用法粗解

热门文章

  1. UniTask使用笔记
  2. java 有序集合_java有哪些有序集合?
  3. [OpenShift 4 - DevSecOps Workshop (16) - 使用 VSCode 编辑运行 Tekton Pipeline 资源
  4. OpenShift 4 Tekton (1) - OpenShift Pipeline入门-安装Pipeline Operator
  5. OpenShift 4 - 查看关键证书到期日期
  6. 将ONNX对象检测模型转换为iOS Core ML(一)
  7. zookeeper 日志查看_Linux环境下安装部署单机Zookeeper
  8. phpstorm 如何设置函数的注释内容
  9. 自动清除html无用css,TinyMCE粘贴HTML代码,避免style属性被自动清除_html/css_WEB-ITnose...
  10. html文字自适应屏幕居中显示,DIV+CSS经典布局[宽度自适应][自动屏幕居中]的实现...