您的位置:首页 > 编程语言 > Java开发

java List删除元素问题及解决办法

2016-08-02 21:49 555 查看
先看一个例子:

删除List中值为2的元素:

List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(2);
list.add(3);
list.add(4);
System.out.println("----------list大小1:--"+list.size());
for (int i = 0; i < list.size(); i++) {
if (2 == list.get(i)) {
list.remove(i);
}
System.out.println(list.get(i));
}
System.out.println("最后输出=" + list.toString());


结果:

----------list大小1:--5

1

2

3

4

最后输出=[1, 2, 3, 4]
可以看到,只删除了一个2,还有一个没有完全删除,原因是:删除了第一个2后,集合里的元素个数减1,后面的元素往前移了1位,此时,第二个2已经移到了索引index=1的位置,而此时i马上i++了,list.get(i)获得的是数据3。同时list.size()的值也在减小。所以最后输出个值。

解决办法一:

可以从后向前遍历倒着删除

List<Integer>list = new LinkedList<Integer>();
list.add(1);
list.add(2);
list.add(2);
list.add(3);
list.add(4);
System.out.println("----------list大小1:--"+list.size());
for (int i = list.size()-1; i >=0; i--) {
if (2 == list.get(i)) {
list.remove(i); continue;
}
System.out.println(list.get(i));
}
System.out.println("最后输出=" + list.toString());


输出结果为:

----------list大小1:--5

4

3

1

最后输出=[1, 3, 4]

解决办法二:可以对删除后的索引进行自减1

List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(2);
list.add(3);
list.add(4);
System.out.println("----------list大小1:--"+list.size());
for (int i = 0; i < list.size(); i++) {
if (2 == list.get(i)) {
list.remove(i);
i--;
continue;
}
System.out.println(list.get(i));
}
System.out.println("最后输出=" + list.toString());  </span>
结果同上

方法三:

List遍历过程中删除元素的推荐做法

还是使用Iterator遍历,但是不用list来remove。

List<Integer> list = new ArrayList<Integer>();  

list.add(1);  

list.add(2);  

list.add(2);  

list.add(3);  

list.add(4);  

System.out.println("----------list大小1:--"+list.size());  

Iterator<Integer> it = list.iterator();  

while(it.hasNext()){  

    Integer item = it.next();  

    if (2 == item) {  

        it.remove();  

    }  

    System.out.println(item);  

}  

System.out.println("最后输出=" + list.toString());

输出结果:

----------list大小1:--5
1
2
2
3
4
最后输出=[1, 3, 4]

此时,两个2被全部删除了。

对于iterator的remove()方法,也有需要我们注意的地方:

1、每调用一次iterator.next()方法,只能调用一次remove()方法。

2、调用remove()方法前,必须调用过一次next()方法。

源码

采用迭代器方法删除的源码:

public Iterator<E> iterator() {
return new Itr();
}


/**
* An optimized version of AbstractList.Itr
*/
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();
}
}


删除指定位置元素方式的源码:

// 移除此列表中指定位置上的元素。
public E remove(int index) {
RangeCheck(index);

modCount++;
E oldValue = (E) 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐