首頁 >Java >java教程 >Java如何在List或Map遍歷過程中刪除元素

Java如何在List或Map遍歷過程中刪除元素

高洛峰
高洛峰原創
2017-01-22 16:25:461918瀏覽

遍歷刪除List或Map中的元素有很多種方法,當運用不當的時候就會產生問題。下面透過這篇文章來再學習學習吧。

一、List遍歷過程中刪除元素

使用索引下標遍歷的方式

範例:刪除清單中的2

public static void main(String[] args) {
  List<Integer> list = new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(2);
  list.add(3);
  list.add(4);
   
  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=" + list.toString());
   
 }

輸出結果:刪除清單中的2

1
2
3
4
list=[1, 2, 3, 4]

輸出結果:了一個2,另一個2被遺漏了,原因是:刪除了第一個2後,集合裡的元素個數減1,後面的元素往前移了1位,導致了第二個2被遺漏了。

使用For循環遍歷的方式

範例:

public static void listIterator2(){
  List<Integer> list = new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(2);
  list.add(3);
  list.add(4);
   
  for (int value : list) {
   if(2 == value){
    list.remove(value);
   }
   System.out.println(value);
  }
   
  System.out.println("list=" + list.toString());
   
 }

  


結果:

Exception in thread "main" 1
2
java.util.ConcurrentModificationException
 at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
 at java.util.ArrayList$Itr.next(Unknown Source)
 at test.ListIterator.listIterator2(ListIterator.java:39)
 at test.ListIterator.main(ListIterator.java:10)

2對

結果:

public static void listIterator3(){
  List<Integer> list = new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(2);
  list.add(3);
  list.add(4);
   
  Iterator<Integer> it = list.iterator();
  while (it.hasNext()){
   Integer value = it.next();
   if (2 == value) {
    it.remove();
   }
    
   System.out.println(value);
  }
   
  System.out.println("list=" + list.toString());
 }


.

public class ConcurrentModificationException extends


RuntimeException當方法偵測到物件的並發修改,但不允許這種修改時,請拋出此異常。


例如,某個執行緒在 Collection 上進行迭代時,通常不允許另一個線性修改該 Collection。通常在這些情況下,迭代的結果是不確定的。如果偵測到這種行為,一些迭代器實作(包括 JRE 提供的所有通用 collection 實作)可能會選擇拋出此異常。執行此操作的迭代器稱為快速失敗 迭代器,因為迭代器很快就完全失敗,而不會冒著在將來某個時間任意發生不確定行為的風險。


注意:此異常不會始終指出物件已經由不同 執行緒並發修改。如果單執行緒發出違反物件協定的方法呼叫序列,則該物件可能會拋出此異常。例如,如果執行緒使用快速失敗迭代器在 collection 上迭代時直接修改該 collection,則迭代器將拋出此異常。


注意:迭代器的快速失敗行為無法得到保證,因為一般來說,不可能對是否出現不同步並發修改做出任何硬性保證。快速失敗作業會盡力拋出 ConcurrentModificationException。因此,為提高此類操作的正確性而編寫一個依賴此異常的程式是錯誤的做法,正確做法是:ConcurrentModificationException 應該僅用於檢測 bug。


Java中的For each實際上使用的是iterator進行處理的。而iterator是不允許集合在iterator使用期間刪除的。所以導致了iterator拋出了ConcurrentModificationException 。

正確的方式

範例:

1
2
2
3
4
list=[1, 3, 4]

   

結果:

public static void main(String[] args) {
 HashMap<String, String> map = new HashMap<String, String>();
 map.put("1", "test1");
 map.put("2", "test2");
 map.put("3", "test3");
 map.put("4", "test4");
  
 //完整遍历Map
 for (Entry<String, String> entry : map.entrySet()) {
  System.out.printf("key: %s value:%s\r\n", entry.getKey(), entry.getValue());
 }
  
 //删除元素
 Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
 while(it.hasNext())
 {
  Map.Entry<String, String> entry= it.next();
  String key= entry.getKey();
  int k = Integer.parseInt(key);
  if(k%2==1)
  {
   System.out.printf("delete key:%s value:%s\r\n", key, entry.getValue());
   it.remove();
  }
 }
  
 //完整遍历Map
 for (Entry<String, String> entry : map.entrySet()) {
  System.out.printf("key: %s value:%s\r\n", entry.getKey(), entry.getValue());
 }
}

結果:

key: 1 value:test1
key: 2 value:test2
key: 3 value:test3
key: 4 value:test4
delete key:1 value:test1
delete key:3 value:test3
key: 2 value:test2
key: 4 value:test4

注意

但對於iterator的remove()方法,也有需要我們注意的地方:

每呼叫一次iterator.next()方法,只能呼叫一次remove()方法。

呼叫remove()方法前,必須呼叫過一次next()方法。

JDK-API中對於remove()方法的描述:

void remove()從迭代器指向的集合中移除迭代器傳回的最後一個元素(可選操作)。每次呼叫 next 只能呼叫一次此方法。如果進行迭代時用呼叫此方法以外的其他方式修改了該迭代器所指向的集合,則迭代器的行為是不明確的。


拋出:UnsupportedOperationException - 如果迭代器不支援 remove 操作。 IllegalStateException - 如果尚未呼叫 next 方法,或在上一次呼叫 next方法之後已經呼叫了remove 方法。

總結

以上就是關於List與Map的遍歷過程中刪除元素的全部內容了,希望本文的內容對大家的學習或工作能帶來一定的幫助,如果有疑問大家可以留言交流。


更多Java如何在List或Map遍歷過程中刪除元素相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn