Iterator接口 也是 Java 集合架構的成員 , 但它與 Collection 系列 、 Map 系列 的集合不 一樣 : Collection系列集合、 Map 系列集合主要用于盛裝其他對象,而 Iterator 則主要用于周遊(即疊代通路) Collection集合中的元素, Iterator 對象也被稱為疊代器 。
Iterator 接口隐藏了各種 Collection實作類的底層細節,向應用程式提供了周遊 Collection 集合元素的統一程式設計接口 。
Iterator 接口裡定義了如下 4 個方法 :
- boolean hasNext(): 如果被疊代的集合元素還沒有被周遊完 ,則傳回 true 。
- Object next(): 傳回集合裡的下一個元素 。
- void remove(): 删除集合裡上一次 next 方法傳回的元素 。
- void forEachRemaining(Consumer action) ,這是 Java 8 為Iterator 新增的預設方法,該方法可使用Lambda 表達式來周遊集合元素 。
下面程式示範了通過 Iterator 接口來周遊集合元素 :
public class IteratorTest
{
public static void main(String[] args)
{
// 建立集合、添加元素的代碼與前一個程式相同
Collection books = new HashSet();
books.add("輕量級Java EE企業應用實戰");
books.add("瘋狂Java講義");
books.add("瘋狂Android講義");
// 擷取books集合對應的疊代器
Iterator it = books.iterator();
while(it.hasNext())
{
// it.next()方法傳回的資料類型是Object類型,是以需要強制類型轉換
String book = (String)it.next();
System.out.println(book);
if (book.equals("瘋狂Java講義"))
{
// 從集合中删除上一次next方法傳回的元素
it.remove();
}
// 對book變量指派,不會改變集合元素本身
book = "測試字元串"; //①
}
System.out.println(books);
}
}
Iterator 僅用于周遊集合 , Iterator 本身并不提供盛裝對象的能力 。
當使用 Iterator 疊代通路 Collection 集合元素時 , Collection 集合裡的元素不能被改變,隻有通過Iterator 的 remove()方法删除上 一 次 next()方法傳回的集合元素才可以;否則将會引發 java .util.ConcurrentModificationException 異常 。 下面程式示範了這一 點 :
public class IteratorErrorTest
{
public static void main(String[] args)
{
// 建立集合、添加元素的代碼與前一個程式相同
Collection books = new HashSet();
books.add("輕量級Java EE企業應用實戰");
books.add("瘋狂Java講義");
books.add("瘋狂Android講義");
// 擷取books集合對應的疊代器
Iterator it = books.iterator();
while(it.hasNext())
{
String book = (String)it.next();
System.out.println(book);
if (book.equals("瘋狂Android講義"))
{
// 使用Iterator疊代過程中,不可修改集合元素,下面代碼引發異常
books.remove(book);
}
}
}
}
Iterator 法代器采用的是快速失敗( fail-fast ) 機制, 一 旦在疊代過程中檢測到該集合己經被修改(通常是程式中的其他線程修改),程式立即引發 ConcurrentModificationException 異常,而不是顯示修改後的結果,這樣可以避免共享資源而引發的潛在問題。
Java 8 起為Iterator 新增了 一個 forEachRemaining(Consumer action)方法,該方法所需的 Consumer參數同樣也是函數式接口 。 當程式調用 Iterator 的 forEachRemaining(Consumer action)周遊集合元素時,程式會依次将集合元素傳給 Consumer的 accept(T t)方法(該接口中唯一的抽象方法) 。
如下程式示範了使用 Lambda 表達式來周遊集合元素:
public class IteratorEach
{
public static void main(String[] args)
{
// 建立集合、添加元素的代碼與前一個程式相同
Collection books = new HashSet();
books.add("輕量級Java EE企業應用實戰");
books.add("瘋狂Java講義");
books.add("瘋狂Android講義");
// 擷取books集合對應的疊代器
Iterator it = books.iterator();
// 使用Lambda表達式(目标類型是Comsumer)來周遊集合元素
it.forEachRemaining(obj -> System.out.println("疊代集合元素:" + obj));
}
}
除了使用疊代器以外,使用 Java 5 提供的 foreach 循環疊代通路集合元素更加便捷 。
如下程式示範了使用 foreach 循環來疊代通路集合元素 :
public class ForeachTest
{
public static void main(String[] args)
{
// 建立集合、添加元素的代碼與前一個程式相同
Collection books = new HashSet();
books.add(new String("輕量級Java EE企業應用實戰"));
books.add(new String("瘋狂Java講義"));
books.add(new String("瘋狂Android講義"));
for (Object obj : books)
{
// 此處的book變量也不是集合元素本身
String book = (String)obj;
System.out.println(book);
if (book.equals("瘋狂Android講義"))
{
// 下面代碼會引發ConcurrentModificationException異常
books.remove(book); //①
}
}
System.out.println(books);
}
}
API: java.util.Iterator
參考:
【1】:《瘋狂Java講義》