关于JAVA中arratlist中删除元素问题

SKY862390450 2019-10-24 06:12:54
哪位大佬前辈知道为什么用这这种方式遍历删除会报错?
...全文
385 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
mymtom 2019-11-26
  • 打赏
  • 举报
回复
建议迭代器;
如果JDK1.8以上的话,可以用removeif

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;

/**
*
*/
public class ArrayListDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(2);
list.add(6);

for (Integer number : list) {
System.out.println(number);
}

Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer number = iterator.next();
if (number.equals(4)) {
try {
iterator.remove();
} catch (Exception e) {
e.printStackTrace();
}
}
}

list.removeIf(new Predicate<Integer>() {
@Override
public boolean test(Integer number) {
return (number.equals(2) || number.equals(4));
}
});

for (Integer number : list) {
System.out.println(number);
}
}
}
jiawenhe123 2019-11-25
  • 打赏
  • 举报
回复
使用迭代器进行遍历,根据条件删除,因为这是快速失败机制导致的。
  • 打赏
  • 举报
回复
你循环的时候删除数据,这个位置就会发生变化,循环就会失效,所以才会出问题
hurtCat 2019-11-13
  • 打赏
  • 举报
回复
原理是fast-fail,即在使用迭代器过程中不允许对集合进行增删改。
JoeKerouac 2019-11-13
  • 打赏
  • 举报
回复
是不是ConcurrentModificationException了?可以参考我这个文章:https://blog.csdn.net/qq_27028561/article/details/103037299
zichen2394 2019-11-12
  • 打赏
  • 举报
回复
倒叙遍历 完美解决。 for (int i = list.size()-1; i >=0 ; i--) { }
viewgroup 2019-11-12
  • 打赏
  • 举报
回复
list.removeIf不好用吗。。直接用实现好的就可以的
  • 打赏
  • 举报
回复
用for循环倒叙删除
  • 打赏
  • 举报
回复
我写过关于这个的博客可以看一下:https://blog.csdn.net/qq_37141773/article/details/99307038
IT_熊 2019-11-08
  • 打赏
  • 举报
回复
引用 5 楼 郅嫣的回复:
建议使用普通for(int i= 0; i<size ; i++)更改遍历下标的方式实现动态删除
从前往后删你确定你这个没有问题?
ml_dark 2019-11-08
  • 打赏
  • 举报
回复
iterator才是线程安全的,而LIST,数组不是
devoid 2019-11-08
  • 打赏
  • 举报
回复
这里的for循环依赖于Iterator的next方法。如果在Iterator循环结束前list的长度变了,next方法就会抛出异常,就像你贴出来的一样。 你可以直接使用Iterator循环和Iterator.remove方法: Iterator<Student> iterator = list.iterator(); Student student; while (iterator.hasNext()) { student = iterator.next(); if (student.getSno().equals(sno)) iterator.remove(); }
夜之眷属 2019-11-02
  • 打赏
  • 举报
回复
foreach增强型循环底层使用的迭代器,所以不能直接使用集合的remove方法,这种循环允许遍历不允许增删,要想删除使用迭代器iterator
kang5789 2019-10-25
  • 打赏
  • 举报
回复
没有上面那么复杂 用java自带的集合就可以

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class ListTest {

public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// for (Integer i : list) {
// System.out.println(i);
// list.remove(i);
// }

List<Integer> list2 = new CopyOnWriteArrayList<>();
list2.add(1);
list2.add(2);
list2.add(3);
list2.add(4);
list2.add(5);
for (Integer i : list2) {
System.out.println(i);
list.remove(i);
}
}
}
dkwuxiang 2019-10-25
  • 打赏
  • 举报
回复
这个时候看源码就好了:
public E remove(int index) {
      // 先检查下标索引是是否越界
      rangeCheck(index);
      // ArrayList的修改次数加1
      modCount++;
      // 获取索引对应的元素值
      E oldValue = elementData(index);
      // 获取删除元素后,需要移动的元素的个数
      int numMoved = size - index - 1;
      if (numMoved > 0)
          // 将元素进行移动拷贝
          System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
      // 最后将多出的位置设置为空,这样说明是没有引用的对象了
      elementData[--size] = null; // Let gc do its work
      // 返回删除的旧值
      return oldValue;
}

//ArrayList中Iterator迭代器的实现
private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        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];
        }

        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();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
}
list.remove() 这个操作,导致modCount++这步操作,将ArrayList的修改次数加1。 在初始化Itr时expectedModCount = modCount = 8 。 在执行next方法的第一步先进行了checkForComodification方法的检查,因为我们之前进行了remove操作,那么modCount数值减一,实际modCount = 7 。 modCount 数值和expectedModCount 数值不相等,抛出ConcurrentModificationException异常。
郅嫣 2019-10-25
  • 打赏
  • 举报
回复
建议使用普通for(int i= 0; i<size ; i++)更改遍历下标的方式实现动态删除
断桥忆 2019-10-25
  • 打赏
  • 举报
回复
引用 3 楼 aping2002881 的回复:
这个是按索引删除的,如果有三个数,索引是0.1.2,你顺序删除一个元素后,索引左移只有0.1了,当你删除索引为2的元素时,这个元素不存在就报错了。你从2往0删除就没问题。
就是list集合是动态的集合,这个动态是指我在删除一个元素的时候那么这个list集合为了保持正确性,集合的长度就要减一,这个元素后边的元素就要向前移动一个位置,就是这个元素后所有元素的下标减一。
若光672 2019-10-25
  • 打赏
  • 举报
回复
因为这个for循环底层是迭代器,不允许删除,记住就好。还有Arrays.asList()这个返回的内部集合,遍历的时候 改操作也会宝座 像这样的小细节 记住就好,在研究下
一个帅逼 2019-10-25
  • 打赏
  • 举报
回复
        List<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(23);
        list.add(6);
        list.add(8);
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
            list.remove(i);
            i--;
        }
        List<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(23);
        list.add(6);
        list.add(8);
        List<Integer> removeList = new ArrayList<>();
        for (Integer integer : list) {
            System.out.println(integer);
            removeList.add(integer);
        }
        list.removeAll(removeList);
        List<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(23);
        list.add(6);
        list.add(8);
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
            iterator.remove();
        }
常用的几种方式
令堂六破 2019-10-24
  • 打赏
  • 举报
回复
这个是按索引删除的,如果有三个数,索引是0.1.2,你顺序删除一个元素后,索引左移只有0.1了,当你删除索引为2的元素时,这个元素不存在就报错了。你从2往0删除就没问题。
加载更多回复(2)

62,628

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧