迭代器刪除集合中的元素


剛開始接觸遇到一個基礎問題:在for循環中刪除元素。拋出的異常是"java.util.ConcurrentModificationException"。

此處梳理總結一下:

  1、模擬異常

 1 @Test
 2 public void testException() {
 3         List<String> list = new ArrayList<>();
 4         list.add("a");
 5         list.add("b");
 6         list.add("c");
 7         list.add("d");
 8         list.add("e");
 9         for (String str : list) {// 當第一個元素被刪除后,此處會拋出異常
10             if ("c".equals(str)) {
11                 list.remove("c");
12          }
13      }
14  }

  執行后拋出異常:

      java.util.ConcurrentModificationException
      at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
      at java.util.ArrayList$Itr.next(ArrayList.java:851)
      at sometest.loop.IteratorDemo.testException(IteratorDemo.java:69)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

  2、解決上面異常的方法 可以用迭代器iterator :  

 1 public static void main(String[] args) {
 2         List<String> list = new ArrayList<>();
 3         list.add("a");
 4         list.add("b");
 5         list.add("c");
 6         list.add("d");
 7         list.add("e");
 8         // 使用迭代器實現刪除元素
 9         Iterator<String> it = list.iterator();
10         while (it.hasNext()) { // 調用hasNext方法判斷是否有元素
11             if ("c".equals(it.next())) { // 獲取當前元素
12                 // 因為使用迭代器的remove方法,指針會同時減一 即就不會因為出現集合的元素和指針數不等拋出異常的問題
13                 it.remove();
14             }
15         }17         list.forEach(s -> System.out.println(s));
18     }

  執行后輸出結果:

            a
            b
            d
            e

  3、除了iterator還可以使用ListIIterator進行遍歷刪除。兩者之間的區別在后續介紹。

 1 @Test
 2 public void testListIterator() {
 3         List<String> list = new ArrayList<>();
 4         list.add("a");
 5         list.add("b");
 6         ListIterator<String> it = list.listIterator();
 7         while (it.hasNext()) { // 調用hasNext方法判斷是否有元素
 8             // 通過下面兩種方法可以得到當前元素的索引位置
 9             System.out.println("當前元素是:" + it.next());
10             System.out.println("下一個元素的索引:" + it.nextIndex());
11             System.out.println("上一個元素的索引:" + it.previousIndex());
12         }
13         // listIterator有add()方法
14         it.add("ff");
15         list.forEach(s -> System.out.println(s));
16 }

  執行后輸出結果:        

      當前元素是:a
      下一個元素的索引:1
      上一個元素的索引:0
      當前元素是:b
      下一個元素的索引:2
      上一個元素的索引:1
      遍歷后元素輸出:
              a
              b
              ff

  集合的iterator和ListIterator的區別:

    凡是實現類Collection接口的集合類,都有一個Iterator方法,用於返回一個實現了Iterator接口的對象,用於集合遍歷;(iterator接口定義了3個方法分別是hasNext(),next(),remove())

    我們在使用集合List和Set的時候,為了實現對其數據的遍歷,我們經常使用到了Iterator。在使用過程中不需要干涉其遍歷過程,只需要每次取出一個你想要的的數據進行處理就可以了。

  但是在有的時候使用也是有不同的。List和Set都有iterator()來取得迭代器。對於List來說,你也可以通過listIterator()取得迭代器,兩種迭代器在有些時候是不能通用的,iterator和ListIterator

  的區別主要是以下方面:

    1.  iterator()方法在set和List接口中都有定義,但是ListIterator()僅存在於list接口中 (或實現類中);

    2.  ListIterator有add()方法,可以向List中添加對象,而Iterator不能。

    3.  ListIterator有Iterator都有的hasNext()和next()方法,可以實現順序向后遍歷,但是ListIterator有hasPrevious()方法和previous方法,可以實現逆向(順序向前)遍歷。Iterator就不可以。

    4.  ListIterator可以定位當前的索引位置,nextIndex()和previousIndex()可以實現。Iterator沒有此功能。

    5.  都可實現刪除對象,但是ListIterator可以實現對對象的修改(set方法可以實現) Iterator沒有此功能。

    因為ListIterator的這些功能,可以實現對LinkedList等List數據結構的操作。其實,數組對象也可以用迭代器來實現。

 

  因為java8的引入可以在刪除元素的時候有了更簡便的方法:

    從JDK1.8開始,可以使用removeIf()方法來代替 Iterator的remove()方法實現一邊遍歷一邊刪除。

 1 @Test
 2 public void testJava8RemoveIf() {
 3         List<String> list = new ArrayList<>();
 4         list.add("a");
 5         list.add("b");
 6         list.add("c");
 7         list.add("d");
 8         list.add("e");
 9         list.removeIf(s->"c".equals(s));
10         list.forEach(s-> System.out.print(s + " "));
11 }

  輸出結果:

    a b d e 


免責聲明!

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



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