list刪除數據有坑勿跳


      有人看到這么標題可能覺得這個真是太easy了,不就remove嗎,分分鍾搞定。但結果卻出乎意料,下面我們來說說list刪除數據可能遇到的坑:

首先我們來初始化一個list

public static void main(String[] args) { ArrayList<String> list=new ArrayList<>(); list.add("華為"); list.add("中軟"); list.add("平安"); list.add("富士康"); list.add("富士康"); list.add("軟通"); list.add("蘇寧"); System.out.println(list);

 

 

坑一:

我在list里添加一些各位大佬們以后要去的公司,突然想把里面的富士康刪除掉。於是

	for (int i = 0; i < list.size(); i++) {
			if ("富士康".equals(list.get(i))) {
				list.remove(i);
			}
		}
		System.out.println(list);

結果輸出:[華為, 中軟, 平安, 富士康, 軟通, 蘇寧]

兩個富士康還剩一個,不徹底嘛。原因很簡單,就是List調用remove(index)方法后,會移除index位置上的元素,index之后的元素就全部依次左移。第二個"富士康"自然躲過一劫。

這時可以對索引同步調整下,代碼如下:

    for (int i = 0; i < list.size(); i++) { if ("富士康".equals(list.get(i))) { list.remove(i--); } } System.out.println(list);

結果為:[華為, 中軟, 平安, 軟通, 蘇寧]

 

坑二:

使用foreach遍歷List刪除元素,代碼如下:

        for (String str : list) { if ("富士康".equals(str)) { list.remove(str); } } System.out.println(list);

結果如下:

Exception in thread "main" java.util.ConcurrentModificationException

居然報錯,什么原因呢?其實foreach 是對的 Iterable、hasNext、next方法的簡寫。我們可以看看List.iterator()的源碼:

private class Itr implements Iterator<E> { int cursor;       // 要返回的下一個元素的索引
int lastRet = -1; // 返回的最后一個元素的索引;如果沒有就返回-1 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(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }

可以看出在 next、remove方法中都會調用checkForComodification 方法,該方法的作用是判斷 modCount != expectedModCount是否相等,

如果不相等則拋出ConcurrentModificationException異常

當我們調用 list.remove(item)時,對 list 對象的 modCount 值進行了修改,

而 list 對象的迭代器的 expectedModCount 值未進行修改

所以就拋出ConcurrentModificationException異常!

但我們可以用迭代器來刪除list數據,代碼如下:

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

結果:[華為, 中軟, 平安, 軟通, 蘇寧]

這是因為Iterator.remove() 方法會在刪除當前迭代對象的同時,會保留原來元素的索引。

所以用迭代刪除元素是最保險的方法,建議大家使用List過程中需要刪除元素時,使用這種方式。

這里需要注意的是如果使用迭代器,用list.remove(str)方法刪除元素,還是會拋ConcurrentModificationException異常。原因上面已經講過!

 

總結:

   1、用for循環遍歷List刪除元素時,需要注意索引會左移的問題。

   2、List刪除元素時,為避免陷阱,建議使用迭代器iterator的remove方式。

   3、List刪除元素時,默認按索引刪除,而不是對象刪除。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM