【Java】删除集合元素的正确与错误做法 我会带着你远行 2024-03-17 17:31 7阅读 0赞 ## 错误做法 ## ### 一、fori正序 + list.remove(num) ### @Test public void test031(){ ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(3); list.add(3); for (int i = 0; i < list.size(); i++) { Integer num=list.get(i); if(num==3){ list.remove(num); } } list.forEach(System.out::println);// 1 3 } ![image.png][] 我们可以看到,集合中有两个3,结果只删掉了第一个,原因是删除第一个3之后,第二个3的下标变成1,缺少了一次检查 ![image.png][image.png 1] 改成方法:删除之后i–,回退一次,见下面的正确做法一 ### 二、增强for + list.remove(num) ### @Test public void test07(){ ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(3); list.add(2); for (Integer num:list) { if(num==1){ list.remove(num); } } list.forEach(System.out::println); } ![image.png][image.png 2] 我们看到报错的是ArrayList内部迭代器的next方法中的checkForCommdification方法抛出ConcurrentModificationException,源码如下 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(); } 我们可以看到modCount != expectedModCount,而抛出异常 原因是remove的时候修改了modCount,但是并未修改expectedModeCount ArrayList的remove(Object o)的源码如下: 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) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work } 修正方法:使用iteritor的remove(),见下面正确方法的三 ## 正确做法 ## ### 一、fori正序 + list.remove(num) + 回退 ### @Test public void test03(){ ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(3); list.add(3); for (int i = 0; i < list.size(); i++) { Integer num=list.get(i); if(num==3){ list.remove(num); i--//注意回退,不然会缺少一次检查 } } list.forEach(System.out::println);// 1 3 } ### 二、fori倒序 + list.remove(num) ### @Test public void test04(){ ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(3); list.add(2); for (int i = list.size()-1; i >=0; i--) { Integer num=list.get(i); if(num==1){ list.remove(num); } } list.forEach(System.out::println); } 倒叙删除不用回退,如下图 ![image.png][image.png 3] ### 三、iterator.remove() ### @Test public void test01(){ ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(3); list.add(2); Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()){ Integer next = iterator.next(); if(next==3){ iterator.remove(); } } list.forEach(System.out::println); } 这种做法不会抛出ConcurrentModificationException的原因是,iterator.remove()也调用了remove(Object o),但是它把modCount的值,也赋值给了exceptionCount 源码如下: 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(); } } ### 四、list.removeIf(条件) ### @Test public void test02(){ ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(3); list.add(3); list.removeIf(next -> next == 3); list.forEach(System.out::println); } ## 注意事项 ## * remove有两个重载方法,一个接收int的index,一个接收Object的o,注意不要写错 [image.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/15/ddb40e16b722491d85e7d97aadc09e36.png [image.png 1]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/15/338d6b6d033844ab90467618da3bff2b.png [image.png 2]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/15/0185832f8af14bb3ba9d4b577b63b55f.png [image.png 3]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/15/ecd4ae082cc14c669abc75c4f71c7e44.png
相关 Java集合操作错误:删除元素后仍访问的问题 在Java中,当你删除一个集合(如List或Set)中的元素时,通常这个元素的引用会被移除。因此,如果你在删除元素后仍然试图通过这个引用访问它,将会抛出`java.lang.N 桃扇骨/ 2024年09月10日 15:12/ 0 赞/ 16 阅读
相关 集合操作错误:ArrayList删除元素时的问题 在Java中,使用ArrayList删除元素时可能会遇到以下几种问题: 1. **索引越界**: 如果要删除的元素索引不在列表范围内,程序会抛出`IndexOutOfB 港控/mmm°/ 2024年09月10日 05:33/ 0 赞/ 21 阅读
相关 Java集合框架操作错误:List删除元素示例 在Java的集合框架中,我们通常使用`remove()`方法来删除特定的元素。以下是一个关于如何使用List(如ArrayList)删除元素的示例: ```java impo 淡淡的烟草味﹌/ 2024年09月05日 15:48/ 0 赞/ 17 阅读
相关 【Java】删除集合元素的正确与错误做法 错误做法 一、fori正序 + list.remove(num) @Test public void test031(){ 我会带着你远行/ 2024年03月17日 17:31/ 0 赞/ 8 阅读
相关 Python--遍历列表时删除元素的正确做法 一.问题描述 这是在工作中遇到的一段代码,原理大概和下面类似(判断某一个元素是否符合要求,不符合删除该元素,最后得到符合要求的列表): a = [1,2,3,4 布满荆棘的人生/ 2023年01月13日 06:18/ 0 赞/ 159 阅读
相关 删除list集合中特定元素的正确姿势 背景 如何删除一个集合对象中的特定元素?小问题,但并不简单。 常见异常: ConcurrentModificationException java.u Myth丶恋晨/ 2023年01月08日 02:07/ 0 赞/ 240 阅读
相关 python删除旧元素_详解Python遍历列表时删除元素的正确做法 一.问题描述 这是在工作中遇到的一段代码,原理大概和下面类似(判断某一个元素是否符合要求,不符合删除该元素,最后得到符合要求的列表): a = \[1,2,3,4,5,6, 秒速五厘米/ 2022年10月25日 14:27/ 0 赞/ 168 阅读
相关 遍历list时删除元素的正确做法 我们往往会遇到需要删除list中满足条件的元素。举例: List<string> list_str =new List<string>() { Bertha 。/ 2022年06月04日 08:12/ 0 赞/ 273 阅读
还没有评论,来说两句吧...