剛開始接觸遇到一個基礎問題:在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