天天看點

在循環中 删除list中元素

文章目錄

    • 周遊
      • 1、for循環
      • 2、foreach()
      • 3、iterator周遊
      • 總結:
    • 擴充: ArrayList源碼
      • remove()
      • iterator()源碼

JAVA中循環周遊list有三種方式for循環、增強for循環(也就是常說的foreach循環)、iterator周遊。

周遊

1、for循環

for(int i=0;i<list.size();i++){
	    if(list.get(i).equals("del"))
	        list.remove(i);
	}
           

這種方式的問題在于:删除某個元素後,list的大小發生了變化,而你的索引也在變化,是以會導緻你在周遊的時候漏掉某些元素。

比如當你删除第1個元素後,後面的元素都往前移動了一位;繼續根據索引通路第2個元素時,實際通路的是原來的第3個元素。

是以,這種方式可以用在删除特定的一個元素時使用,但不适合循環删除多個元素時使用。

2、foreach()

for(String x:list){
	    if(x.equals("del"))
	        list.remove(x);
	}
           

這種方式的問題在于,删除元素後繼續循環會報錯誤資訊ConcurrentModificationException,因為元素在使用的時候發生了并發的修改,導緻異常抛出。

但若删除完畢馬上使用break跳出,則不會觸發報錯。

在循環中 删除list中元素

3、iterator周遊

Iterator<String> it = list.iterator();
		while(it.hasNext()){
		    String x = it.next();
		    if(x.equals("del")){
		        it.remove();
		    }
		}
           

iterator方式可以正常的循環及删除。

 但如果用list的remove方法同樣會報上面提到的ConcurrentModificationException錯誤。

總結:

(1)循環删除list中特定一個元素的,可以使用三種方式中的任意一種,但在使用中要注意上面分析的各個問題。

(2)循環删除list中多個元素的,應該使用疊代器iterator方式。

擴充: ArrayList源碼

remove()

/**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).
     *
     * @param index the index of the element to be removed
     * @return the element that was removed from the list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index); // 要删除的元素

        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

        return oldValue;
    }
           

iterator()源碼

public Iterator<E> iterator() {
        return new 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;

        Itr() {}

        。。。
          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 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 boolean hasNext() {
            return cursor != size;
        }