一、迭代器Iterator
介面:Iterator
public interface Iterator<E>{ boolean hasNext(); E next(); void remove(); }
查看Iterator介面API可以知道,這是對collection進行迭代的迭代器。迭代器允許呼叫者利用定義良好的語意在迭代期間從迭代器所指向的 collection 移除元素。
尤其值得注意的是此迭代器remove()方法的使用:從迭代器指向的 collection 中移除迭代器返回的最後一個元素(可選操作)。每次呼叫 next 只能呼叫一次此方法。如果進行迭代時以呼叫此方法(remove方法)以外的其他方式修改了該迭代器所指向的 collection,則迭代器的行為是不確定的。 介面設計人員在設計Iterator
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class ItaratorTest { public static void main(String[] args) { Collection<String> list = new ArrayList<String>(); list.add("Android"); list.add("IOS"); list.add("Windows Mobile"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String lang = iterator.next(); list.remove(lang);//will throw ConcurrentModificationException } } }
此段程式碼在執行時會拋出ConcurrentModificationException異常,因為我們在迭代器運行期間沒有用iterator的remove()方法來刪除元素,而是使用ArrayList的remove()方法改變了迭代器所指向的collection。這就違反了迭代器的設計原則,所以發生了異常。
所報異常情況如下所示:
Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) at java.util.ArrayList$Itr.next(ArrayList.java:831) at Text.ItaratorTest.main(ItaratorTest.java:17)
二、for-each循環與迭代器Iterator
從Java5起,在Java中有了for-each循環,可以用來循環遍歷collection和array。 Foreach迴圈允許你在無需保持傳統for迴圈中的索引,或在使用iterator /ListIterator(ArrayList中的一種迭代器實作)時無需呼叫while迴圈中的hasNext()方法就能遍歷collection。 for-each迴圈簡化了任何Collection或array的遍歷過程。但是使用foreach循環也有兩點需要注意。
使用foreach循環的對象,必須實作了Iterable
請看如下範例:
import java.util.ArrayList; public class ForeachTest1 { public static void main(String args[]) { CustomCollection<String> myCollection = new CustomCollection<String>(); myCollection.add("Java"); myCollection.add("Scala"); myCollection.add("Groovy"); // What does this code will do, print language, throw exception or // compile time error for (String language : myCollection) { System.out.println(language); } } private class CustomCollection<T> { private ArrayList<T> bucket; public CustomCollection() { bucket = new ArrayList(); } public int size() { return bucket.size(); } public boolean isEmpty() { return bucket.isEmpty(); } public boolean contains(T o) { return bucket.contains(o); } public boolean add(T e) { return bucket.add(e); } public boolean remove(T o) { return bucket.remove(o); } } }
上述程式碼將無法透過編譯,這是因為程式碼中的CustomCollection類別沒有實作Iterable
Exception in thread "main" java.lang.Error: Unresolved compilation problem: Can only iterate over an array or an instance of java.lang.Iterable at Text.ForeachTest1.main(ForeachTest1.java:15)
事實上,無需等到編譯時才發現報錯,eclipse會在這段程式碼寫完之後就會在foreach循環處顯示錯誤:Can only iterate over an array or an instance of java.lang.Iterable
從上述範例可以再次確認的是,foreach循環只適用於實作了Iterable
import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Iterator; public class ForeachTest { public static void main(String args[]) { CustomCollection<String> myCollection = new CustomCollection<String>(); myCollection.add("Java"); myCollection.add("Scala"); myCollection.add("Groovy"); for (String language : myCollection) { System.out.println(language); } } private static class CustomCollection<T> extends AbstractCollection<T> { private ArrayList<T> bucket; public CustomCollection() { bucket = new ArrayList(); } public int size() { return bucket.size(); } public boolean isEmpty() { return bucket.isEmpty(); } public boolean contains(Object o) { return bucket.contains(o); } public boolean add(T e) { return bucket.add(e); } public boolean remove(Object o) { return bucket.remove(o); } @Override public Iterator<T> iterator() { // TODO Auto-generated method stub return bucket.iterator(); } } }
2.foreach循環的內部實現也是依靠Iterator進行實現的
為了驗證foreach循環是使用Iterator作為內部實現這一事實,我們依然採用本文最開始的實例進行驗證:
reee程式執行時期所報異常:
public class ItaratorTest { public static void main(String[] args) { Collection<String> list = new ArrayList<String>(); list.add("Android"); list.add("IOS"); list.add("Windows Mobile"); // example1 // Iterator<String> iterator = list.iterator(); // while (iterator.hasNext()) { // String lang = iterator.next(); // list.remove(lang); // } // example 2 for (String language : list) { list.remove(language); } } }
此異常正說明了for-each循環內部使用了Iterator來遍歷Collection,它也調用了Iterator.next(),這會檢查(元素的)變化並拋出ConcurrentModificationException。
總結:
在遍歷collection時,如果要在遍歷期間修改collection,則必須透過Iterator/listIterator來實現,否則可能會發生「不確定的後果」。
foreach循環透過iterator實現,使用foreach循環的物件必須實現Iterable介面

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

禪工作室 13.0.1
強大的PHP整合開發環境

Atom編輯器mac版下載
最受歡迎的的開源編輯器

Dreamweaver CS6
視覺化網頁開發工具

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能