您好,登录后才能下订单哦!
Java中的remove()元素怎么利用List遍历进行删除?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
一、几种常见的遍历方式
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<E> 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时,使用倒序遍历的方式最为妥当。
关于Java中的remove()元素怎么利用List遍历进行删除问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。