Java ArrayList删除特定元素的方法

开发 后端
ArrayList是最常用的一种java集合,在开发中我们常常需要从ArrayList中删除特定元素。
ArrayList是最常用的一种java集合,在开发中我们常常需要从ArrayList中删除特定元素。有几种常用的方法:

Java ArrayList删除特定元素的方法



最朴实的方法,使用下标的方式:
ArrayList al = new ArrayList(); 
 
al.add("a"); 
 
al.add("b"); 
 
//al.add("b"); 
 
//al.add("c"); 
 
//al.add("d"); 
 
for (int i = 0; i < al.size(); i++) { 
 
if (al.get(i) == "b") { 
 
al.remove(i); 
 
i--; 
 

 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
在代码中,删除元素后,需要把下标减一。这是因为在每次删除元素后,ArrayList会将后面部分的元素依次往上挪一个位置(就是copy),所以,下一个需要访问的下标还是当前下标,所以必须得减一才能把所有元素都遍历完

还有另外一种方式:
ArrayList al = new ArrayList(); 
 
al.add("a"); 
 
al.add("b"); 
 
al.add("b"); 
 
al.add("c"); 
 
al.add("d"); 
 
for (String s : al) { 
 
if (s.equals("a")) { 
 
al.remove(s); 
 

 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
此处使用元素遍历的方式,当获取到的当前元素与特定元素相同时,即删除元素。从表面上看,代码没有问题,可是运行时却报异常:
Exception in thread "main" java.util.ConcurrentModificationException 
 
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:886
 
at java.util.ArrayList$Itr.next(ArrayList.java:836
 
at com.mine.collection.TestArrayList.main(TestArrayList.java:17
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

从异常堆栈可以看出,是ArrayList的迭代器报出的异常,说明通过元素遍历集合时,实际上是使用迭代器进行访问的。可为什么会产生这个异常呢?打断点单步调试进去发现,是这行代码抛出的异常:
final void checkForComodification() { 
 
if (modCount != expectedModCount) 
 
throw new ConcurrentModificationException(); 
 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
modCount是集合修改的次数,当remove元素的时候就会加1,初始值为集合的大小。迭代器每次取得下一个元素的时候,都会进行判断,比较集合修改的次数和期望修改的次数是否一样,如果不一样,则抛出异常。查看集合的remove方法:
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 
 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
可以看到,删除元素时modCount已经加一,但是expectModCount并没有增加。所以在使用迭代器遍历下一个元素的时候,会抛出异常。那怎么解决这个问题呢?其实使用迭代器自身的删除方法就没有问题了
ArrayList al = new ArrayList(); 
 
al.add("a"); 
 
al.add("b"); 
 
al.add("b"); 
 
al.add("c"); 
 
al.add("d"); 
 
Iterator iter = al.iterator(); 
 
while (iter.hasNext()) { 
 
if (iter.next().equals("a")) { 
 
iter.remove(); 
 

 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
查看迭代器自身的删除方法,果不其然,每次删除之后都会修改expectedModCount为modCount。这样的话就不会抛出异常
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(); 
 

 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
建议以后操作集合类的元素时,尽量使用迭代器。可是还有一个地方不明白,modCount和expectedModCount这两个变量究竟是干什么用的?为什么集合在进行操作时需要修改它?为什么迭代器在获取下一个元素的时候需要判断它们是否一样?它们存在总是有道理的吧

其实从异常的类型应该是能想到原因:ConcurrentModificationException.同时修改异常。看下面一个例子
List list = new ArrayList(); 
 
// Insert some sample values. 
 
list.add("Value1"); 
 
list.add("Value2"); 
 
list.add("Value3"); 
 
// Get two iterators. 
 
Iterator ite = list.iterator(); 
 
Iterator ite2 = list.iterator(); 
 
// Point to the first object of the list and then, remove it. 
 
ite.next(); 
 
ite.remove(); 
 
/* The second iterator tries to remove the first object as well. The object does not exist and thus, a ConcurrentModificationException is thrown. */ 
 
ite2.next(); 
 
ite2.remove(); 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
同样的,也会报出ConcurrentModificationException。
责任编辑:王雪燕 来源: codeceo
相关推荐

2012-03-19 09:57:09

JavaArrayList

2012-05-29 15:29:14

JavaArrayList

2015-08-04 09:18:26

JavaArrayList元素

2015-12-14 09:42:34

Java不同排序方法

2024-01-05 15:06:04

元素程序员review

2009-11-16 16:31:56

PHP数组删除

2021-07-22 09:53:34

Vector类Java添加元素

2020-12-14 08:03:52

ArrayList面试源码

2022-01-20 09:58:44

Python元素列表

2020-08-26 07:36:14

sed命令Linux

2016-12-29 16:25:32

字符串算法代码

2024-06-03 10:07:22

Vector类元素向量

2021-07-12 11:01:15

Vector元素方法

2010-09-08 13:14:57

SQL删除约束

2012-01-12 13:24:55

Java

2022-01-07 19:50:14

元素java集合

2024-02-22 08:59:41

JavaArrayListLinkedList

2009-11-30 18:21:21

PHP删除数组元素

2011-08-12 11:04:47

Oracle数据库增删集合元素Java

2019-11-06 16:21:25

ArrayListLinkedListVector
点赞
收藏

51CTO技术栈公众号