千家信息网

Java如何遍历集合并把其中的某些元素删除

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇内容介绍了"Java如何遍历集合并把其中的某些元素删除"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所
千家信息网最后更新 2026年11月02日Java如何遍历集合并把其中的某些元素删除

本篇内容介绍了"Java如何遍历集合并把其中的某些元素删除"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

本文基于jdk1.8来分析ArrayList的源码

首先是主要的成员变量。

  /**   * Default initial capacity.   **/  private static final int DEFAULT_CAPACITY = 10;  /**   * Shared empty array instance used for empty instances.   **/  private static final Object[] EMPTY_ELEMENTDATA = {};  /**   * Shared empty array instance used for default sized empty instances. We   * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when   * first element is added.   **/  private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};  /**   * The array buffer into which the elements of the ArrayList are stored.   * The capacity of the ArrayList is the length of this array buffer. Any   * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA   * will be expanded to DEFAULT_CAPACITY when the first element is added.   **/  transient Object[] elementData; // non-private to simplify nested class access  /**   * The size of the ArrayList (the number of elements it contains).   *   * @serial   **/  private int size;

其中初始大小为10,size表示集合中元素的个数。此外,还有两个空数组EMPTY_ELEMENTDATA,和DEFAULTCAPACITY_EMPTY_ELEMENTDATA。通过DEFAULTCAPACITY_EMPTY_ELEMENTDATA的注释,我们可以了解到,这个变量区别于EMPTY_ELEMENTDATA,主要是为了决定第一个元素插入时,扩容多大的问题。从这里的描述可以理解到,ArrayList创建好后,其实并没有真正分配数组空间,而是在第一个元素插入时,才分配的空间。这一点是区别于jdk1.6的。在jdk1.6中,ArrayList一创建,数据空间就默认分配好了,10个或指定的空间。jdk1.8这么做,可以做到空间延迟分配,提高程序性能。

接下来看一下构造函数。

/**   * Constructs an empty list with an initial capacity of ten.   **/  public ArrayList() {    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;  }/**   * Constructs an empty list with the specified initial capacity.   *   * @param initialCapacity the initial capacity of the list   * @throws IllegalArgumentException if the specified initial capacity   *     is negative   **/  public ArrayList(int initialCapacity) {    if (initialCapacity > 0) {      this.elementData = new Object[initialCapacity];    } else if (initialCapacity == 0) {      this.elementData = EMPTY_ELEMENTDATA;    } else {      throw new IllegalArgumentException("Illegal Capacity: "+                        initialCapacity);    }  }

无参构造函数,将创建一个长度为0的空数组。

有参构造函数,参数大于0时正常创建数组,参数为0时,也是创建长度为0的数组。但它和无参构造函数创建的空数组是可以区别开的,它们使用了不同的对象。

接下来是插入元素add。

/**   * Appends the specified element to the end of this list.   *   * @param e element to be appended to this list   * @return true (as specified by {@link Collection#add})   **/  public boolean add(E e) {    ensureCapacityInternal(size + 1); // Increments modCount!!    elementData[size++] = e;    return true;  } private void ensureCapacityInternal(int minCapacity) {    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));  } private static int calculateCapacity(Object[] elementData, int minCapacity) {    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {      return Math.max(DEFAULT_CAPACITY, minCapacity);    }    return minCapacity;  } private void ensureExplicitCapacity(int minCapacity) {    modCount++;    // overflow-conscious code    if (minCapacity - elementData.length > 0)      grow(minCapacity);  }

通过calculateCapacity函数,我们可以知道,如果是用new ArrayList()创建的list,第一次add元素,计算得minCapacity = 1。如果是new ArrayList(0)创建的list,计算得minCapacity = 10. 然后再根据minCapacity去grow。

get方法比较简单,这里不再分析。

ArrayList的一个常见问题是ConcurrentModificationException,同步修改异常,也称为快速失败,fast-fail。当我们以foreach方式遍历ArrayList时,如果在遍历过程中删除ArrayList的元素,或者别的线程往ArrayList中添加元素,就会抛出该异常。这里需要注意,以for(int i = 0; i < list.size(); i++)的方式遍历ArrayList时,是不会抛出同步修改异常的,但用这种方式遍历,需要处理好i的前进速度。

那么,用foreach方式遍历ArrayList为什么会抛出同步修改异常呢?

foreach代码的底层实现,是用iterator对ArrayList进行遍历,在遍历过程中,会持续调用next获取下一个元素。next方法中,会首先checkForComodification(),它的作用是检查modCount和expectedModCount是否相等。不相等时,则抛出同步修改异常。那么什么情况下修改次数和期望修改次数不相等呢?这里需要首先弄明白,modCount和expectedModCount是什么东西?modCount是ArrayList从它的父类继承来的属性,记录了集合的修改次数,add,remove时都会给modCount加1. expectedModCount是迭代器的成员变量,它是在创建迭代器时,取的modCount的值,并且,在遍历过程中不再改变。那么就清楚了,expectedModCount其实是开始遍历时modCount的值,如果在遍历过程中,ArrayList进行了add或remove操作,那么必然导致expectedModCount和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];    }    final void checkForComodification() {      if (modCount != expectedModCount)        throw new ConcurrentModificationException();    }

那么,同步修改异常如何避免呢?或者说,我们如何遍历集合并把其中的某些元素删除呢?

答案是使用迭代器的remove方法删除元素。在迭代器的remove方法中,删除元素后,会重新把modCount赋值给expectedModCount,所以,它不会抛出同步修改异常。

 public void remove() {      if (lastRet < 0)        throw new IllegalStateException();      checkForComodification();      try {        ArrayList.this.remove(lastRet);        cursor = lastRet;        lastRet = -1;        expectedModCount = modCount;      } catch (IndexOutOfBoundsException ex) {        throw new ConcurrentModificationException();      }    }

"Java如何遍历集合并把其中的某些元素删除"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

元素 同步 数组 函数 空间 过程 方式 方法 分配 迭代 变量 次数 接下来 内容 参数 情况 成员 是在 更多 知识 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 苏州找大状互联网科技有限公司 互联网属科技 互联网最新的科技 科技与互联网 互联网下的科技发展 互联网公司 科技公司 互联网科技的发展 互联网科技logo设计 撒么互联网科技公司 富国互联网科技创新基金 中国科技互联网公司收入 阿大互联网科技有限公司 健康食品互联网创新科技园项目 银川新华互联网科技学校联系电话 本届互联网博览会上的黑科技 允成互联网科技有限公司融资 互联网企业科技类企业如何做账 全球科技与互联网公司市值变化 广西科技产业互联网是什么 陕西九四连强互联网科技有限公司 上海挚品互联网科技有限公司 科技类互联网 喔噻互联网科技 互联网科技集团 互联网科技股有哪些 互联网科技公司营业执照怎么办理 高科技互联网套路 南通创西澳互联网科技有限公司 求路客互联网科技电话 互联网科技创业有什么好项目
0