“嗨,阿米戈!”

“嗨,艾莉!”

“今天我想給大家講講迭代器。”

“迭代器實際上是與集合同時發明的。集合的主要目的是存儲元素,而迭代器的主要目的是一個一個地檢索這些元素。”

“搞到一套元素有什麼難的?”

“首先,一些集合中的元素,例如 Set,沒有既定的順序和/或順序不斷變化。”

“其次,一些數據結構可能以非常複雜的方式存儲對象:在不同的組、列表等中。換句話說,按順序分發所有元素將是一項非常重要的任務。”

“第三,集合往往會發生變化。假設您決定顯示集合的全部內容,但就在輸出中間,JVM 切換到另一個線程,該線程替換了集合的一半元素。因此,您得到的不是輸出,而是誰知道呢。”

“唔...”

“但是!這些正是迭代器可以解決的問題。迭代器是集合中的一個特殊對象,一方面可以訪問其所有私有數據並知道其內部結構,另一方面,實現了公共 Iterator 接口,讓每個人都知道如何使用它。

“一些迭代器有一個內部數組,當創建迭代器時,集合中的所有元素都會被複製到這個數組中。這確保了對集合的任何後續更改都不會影響元素的數量或順序。”

“我認為你在使用for each時遇到過這個問題。你不能同時遍歷一個集合併從中刪除元素。這完全是因為迭代器的工作方式。”

“在添加到並發庫的新集合中,迭代器被重新設計以消除這個問題。”

“讓我提醒你迭代器是如何工作的。”

“Java 有一個特殊的 Iterator 接口。這是它的方法:”

Iterator<E> 接口的方法 描述
boolean hasNext() 檢查是否還有更多元素
E next() 返回當前元素並移動到下一個。
void remove() 移除當前元素

“迭代器可讓您連續獲取集合的所有元素。將迭代器視為類似於 InputStream 的東西更合乎邏輯——它擁有所有數據,但其任務是按順序輸出數據。”

“   next () 方法返回集合中的下一個元素。”

hasNext () 方法用於檢查是否還有更多元素。”

“而remove () 移除當前元素。”

“任何問題?”

“為什麼這些方法有這麼奇怪的名字?為什麼不是 isEmpty() 和 getNextElement()?”

“那不是更有意義嗎?”

“這會更有意義,但名稱來自 C++ 語言,其中迭代器出現得更早。”

“原來如此,我們繼續吧。”

“除了迭代器,還有一個Iterable接口,所有支持迭代器的集合都必須實現這個接口,它只有一個方法:”

Iterable<T> 接口的方法 描述
Iterator<T>iterator() 返回一個迭代器對象

“您可以在任何集合上使用此方法來獲取迭代器對像以遍歷其元素。讓我們遍歷 TreeSet 中的所有元素

例子
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

while (iterator.hasNext())
{
 String item = iterator.next();
 System.out.println(item);
}

“像這樣使用迭代器不是很方便——有太多多餘和明顯的代碼。當for-each循環出現在 Java 中時,情況變得更簡單了。”

“現在這段代碼更加緊湊和可讀:”

TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

while (iterator.hasNext())
{
 String item = iterator.next();
 System.out.println(item);
}
TreeSet<String> set = new TreeSet<String>();

for(String item : set)
{
 System.out.println(item);
}

“這是相同的代碼!兩種情況下都使用了迭代器。”

“只是它的使用隱藏在for-each循環中,注意右邊的代碼根本沒有紅字,完全隱藏了迭代器的使用。”

for-each循環可用於支持迭代器的任何對象。換句話說,您可以編寫自己的類,向其添加 iterator () 方法,並在 for-each 構造中使用其對象

“哇!當然,我並不急於編寫自己的集合和迭代器,但前景仍然很誘人。我會記下來的。”

此外,還有另一種流行的迭代器類型,它甚至有自己的接口。我說的是列表迭代器,即ListIterator

“不管它們的實現如何,列表都會保持元素的順序,這使得通過迭代器使用它們更方便一些。”

“這是ListIterator <E> 接口的方法:”

方法 描述
boolean hasNext() 檢查前面是否還有更多元素。
E next() 返回下一個元素。
int nextIndex() 返回下一個元素的索引
void set(E e) 改變當前元素的值
boolean hasPrevious() 檢查後面是否有任何元素。
E previous() 返回前一個元素
int previousIndex() 返回前一個元素的索引
void remove() 移除當前元素
void add(E e) 將一個元素添加到列表的末尾。

“換句話說,在這裡我們可以向前和向後移動。還有一些其他的小特徵。”

“嗯,那是個有趣的東西。它用在什麼地方?”

“假設你想在鍊錶上來回移動。get 操作會相當慢,但 next() 操作會非常快。”

“嗯,你說服了我,我會記住的。”

“謝謝,艾莉!”