
1. 引言在 Java 集合框架中迭代器Iterator是遍歷集合元素的核心接口。無論是ArrayList、HashSet還是HashMap都可以通過迭代器統(tǒng)一地訪問其中的元素而不必關(guān)心底層數(shù)據(jù)結(jié)構(gòu)的具體實現(xiàn)。本文將深入講解 Java 迭代器接口的設(shè)計原理、常用方法、實現(xiàn)機制以及實際應(yīng)用場景幫助你徹底掌握這一重要知識點。2. Iterator 接口概述Iterator接口位于java.util包中是 Java 集合框架的根接口之一。它提供了一種統(tǒng)一的方式來遍歷集合中的元素屏蔽了不同集合底層實現(xiàn)的差異。2.1 接口定義publicinterfaceIteratorE{booleanhasNext();// 判斷是否還有下一個元素Enext();// 返回下一個元素defaultvoidremove(){thrownewUnsupportedOperationException();}defaultvoidforEachRemaining(Consumer?superEaction){...}}2.2 核心方法說明方法返回值作用hasNext()boolean判斷集合中是否還有未遍歷的元素next()E返回迭代器當(dāng)前位置的下一個元素并將指針后移remove()void從集合中移除迭代器最后返回的元素可選操作forEachRemaining()void對剩余所有元素執(zhí)行指定操作Java 8 新增3. 迭代器的基本使用3.1 標(biāo)準(zhǔn)遍歷模式importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;publicclassIteratorDemo{publicstaticvoidmain(String[]args){ListStringfruitsnewArrayList();fruits.add(蘋果);fruits.add(香蕉);fruits.add(橙子);// 使用迭代器遍歷IteratorStringiteratorfruits.iterator();while(iterator.hasNext()){Stringfruititerator.next();System.out.println(fruit);}}}3.2 使用 forEachRemaining 簡化遍歷IteratorStringiteratorfruits.iterator();iterator.forEachRemaining(System.out::println);3.3 迭代器與增強 for 循環(huán)的關(guān)系增強 for 循環(huán)for-each本質(zhì)上就是迭代器的語法糖// 增強 for 循環(huán)for(Stringfruit:fruits){System.out.println(fruit);}// 等價于迭代器寫法IteratorStringiteratorfruits.iterator();while(iterator.hasNext()){Stringfruititerator.next();System.out.println(fruit);}4. 迭代器遍歷時的刪除操作4.1 使用迭代器的 remove 方法importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;publicclassIteratorRemoveDemo{publicstaticvoidmain(String[]args){ListIntegernumbersnewArrayList();for(inti1;i10;i){numbers.add(i);}// 刪除所有偶數(shù)IteratorIntegeriteratornumbers.iterator();while(iterator.hasNext()){Integernumiterator.next();if(num%20){iterator.remove();// 安全刪除}}System.out.println(numbers);// 輸出: [1, 3, 5, 7, 9]}}4.2 為什么不能在遍歷時直接調(diào)用集合的 remove// 錯誤示例會拋出 ConcurrentModificationExceptionfor(Integernum:numbers){if(num%20){numbers.remove(num);// 拋出異常}}這是因為集合內(nèi)部維護了一個modCount修改次數(shù)計數(shù)器迭代器在創(chuàng)建時會記錄當(dāng)前的modCount。當(dāng)集合結(jié)構(gòu)被直接修改時modCount會變化迭代器檢測到不一致就會拋出ConcurrentModificationException。4.3 使用 remove 方法的注意事項在調(diào)用remove()之前必須先調(diào)用next()否則會拋出IllegalStateExceptionremove()只能移除迭代器最后返回的元素并非所有集合都支持remove()操作不支持時會拋出UnsupportedOperationException5. ListIterator 接口ListIterator是Iterator的子接口專門用于List類型的集合提供了雙向遍歷和元素修改的能力。5.1 接口定義publicinterfaceListIteratorEextendsIteratorE{booleanhasPrevious();// 是否有前一個元素Eprevious();// 返回前一個元素intnextIndex();// 返回下一個元素的索引intpreviousIndex();// 返回前一個元素的索引voidset(Ee);// 替換最后返回的元素voidadd(Ee);// 在當(dāng)前位置插入元素}5.2 雙向遍歷示例importjava.util.ArrayList;importjava.util.List;importjava.util.ListIterator;publicclassListIteratorDemo{publicstaticvoidmain(String[]args){ListStringlistnewArrayList();list.add(A);list.add(B);list.add(C);// 正向遍歷ListIteratorStringiteratorlist.listIterator();System.out.println(正向遍歷:);while(iterator.hasNext()){System.out.print(iterator.next() );// A B C}// 反向遍歷System.out.println(\n反向遍歷:);while(iterator.hasPrevious()){System.out.print(iterator.previous() );// C B A}}}5.3 使用 ListIterator 修改元素ListIteratorStringiteratorlist.listIterator();while(iterator.hasNext()){Stringelementiterator.next();if(B.equals(element)){iterator.set(BB);// 將 B 替換為 BB}}System.out.println(list);// 輸出: [A, BB, C]6. 迭代器的 fail-fast 機制6.1 什么是 fail-fastfail-fast快速失敗是 Java 集合框架的一種錯誤檢測機制。當(dāng)多個線程同時對集合進行結(jié)構(gòu)性修改時迭代器會立即拋出ConcurrentModificationException而不是在將來某個不確定的時間點出現(xiàn)問題。6.2 觸發(fā)條件ListStringlistnewArrayList();list.add(A);list.add(B);IteratorStringiteratorlist.iterator();list.add(C);// 結(jié)構(gòu)性修改while(iterator.hasNext()){System.out.println(iterator.next());// 拋出 ConcurrentModificationException}6.3 如何避免 fail-fast單線程環(huán)境下使用迭代器的remove()方法而不是集合的remove()方法多線程環(huán)境下使用CopyOnWriteArrayList等并發(fā)容器使用Collections.synchronizedList()包裝集合7. 自定義迭代器實現(xiàn)7.1 實現(xiàn) Iterable 接口importjava.util.Iterator;importjava.util.NoSuchElementException;publicclassMyCollectionTimplementsIterableT{privateObject[]elements;privateintsize;publicMyCollection(intcapacity){elementsnewObject[capacity];size0;}publicvoidadd(Telement){if(sizeelements.length){elements[size]element;}}OverridepublicIteratorTiterator(){returnnewIteratorT(){privateintcurrentIndex0;OverridepublicbooleanhasNext(){returncurrentIndexsize;}OverrideSuppressWarnings(unchecked)publicTnext(){if(!hasNext()){thrownewNoSuchElementException();}return(T)elements[currentIndex];}};}publicstaticvoidmain(String[]args){MyCollectionStringcollectionnewMyCollection(5);collection.add(Java);collection.add(Python);collection.add(Go);for(Stringlang:collection){System.out.println(lang);}}}7.2 迭代器設(shè)計原則迭代器應(yīng)該獨立于集合的存儲結(jié)構(gòu)迭代器應(yīng)該支持快速失敗機制迭代器應(yīng)該實現(xiàn)Iterable接口以支持增強 for 循環(huán)8. 迭代器與 Stream 的對比特性IteratorStream遍歷方式外部迭代內(nèi)部迭代是否可復(fù)用不可復(fù)用不可復(fù)用支持函數(shù)式操作不支持支持惰性求值不支持支持并行處理不支持支持// 使用 Stream 替代迭代器ListStringresultfruits.stream().filter(s-s.length()2).map(String::toUpperCase).collect(Collectors.toList());9. 常見問題與最佳實踐9.1 常見問題ConcurrentModificationException遍歷時修改集合結(jié)構(gòu)NoSuchElementException調(diào)用next()時沒有檢查hasNext()IllegalStateException調(diào)用remove()前沒有調(diào)用next()9.2 最佳實踐遍歷時刪除元素優(yōu)先使用迭代器的remove()方法使用增強 for 循環(huán)簡化代碼但需要刪除時使用顯式迭代器多線程環(huán)境下使用并發(fā)集合類優(yōu)先使用 Stream API 處理復(fù)雜的數(shù)據(jù)操作10. 總結(jié)迭代器是 Java 集合框架中不可或缺的組成部分它提供了一種統(tǒng)一、安全的方式來遍歷集合元素。通過本文的學(xué)習(xí)我們掌握了Iterator接口的核心方法及其使用場景ListIterator的雙向遍歷和元素修改能力fail-fast 機制的原理和避免方法自定義迭代器的實現(xiàn)方式迭代器與 Stream API 的對比和選擇在實際開發(fā)中合理選擇遍歷方式能夠提高代碼的可讀性和性能。希望本文能幫助你更好地理解和使用 Java 迭代器接口。