首頁 Java java教程 Java集合Iterator迭代的實作方法

Java集合Iterator迭代的實作方法

Jan 23, 2017 pm 05:00 PM

我們常常使用 JDK 提供的迭代介面進行 Java 集合的迭代。

Iterator iterator = list.iterator();
while(iterator.hasNext()){
String string = iterator.next();
//do something
}
登入後複製

迭代其實我們可以簡單地理解為遍歷,是一個標準化遍歷各類容器裡面的所有物件的方法類,它是一個很典型的設計模式。 Iterator 模式是用於遍歷集合類別的標準存取方法。它可以把存取邏輯從不同類型的集合類別中抽象化出來,從而避免向客戶端揭露集合的內部結構。 在沒有迭代器時我們都是這樣處理的。如下:

對於數組我們是使用下標來進行處理的:

int[] arrays = new int[10];
for(int i = 0 ; i < arrays.length ; i++){
int a = arrays[i];
//do something
}
登入後複製

對於ArrayList 是這麼處理的:

List<String> list = new ArrayList<String>();
for(int i = 0 ; i < list.size() ; i++){
String string = list.get(i);
//do something
}
登入後複製

對於這兩種方式,我們總是都知道集合的內部結構事先都知道,存取程式碼和集合本身是緊密耦合的,無法將存取邏輯從集合類別和客戶端程式碼中分離出來。同時每一種集合對應一種遍歷方法,客戶端程式碼無法重複使用。 在實際應用中如何需要將上面將兩個集合整合是相當麻煩的。所以為了解決以上問題, Iterator 模式騰空出世,它總是用同一種邏輯遍歷集合。使得客戶端本身不需要來維護集合的內部結構,所有的內部狀態都由 Iterator 來維護。客戶端從不直接和集合類別打交道,它總是控制 Iterator,向它發送”向前”,”向後”,”取當前元素”的命令,就可以間接遍歷整個集合。

上面只是對 Iterator 模式進行簡單的說明,下面我們看看 Java 中 Iterator 接口,看他是如何來進行實現的。

一、java.util.Iterator

在 Java 中 Iterator 為一個接口,它只提供了迭代了基本規則,在 JDK 中他是這樣定義的:對 collection 進行迭代的迭代器。迭代器取代了 Java Collections Framework 中的 Enumeration。迭代器與枚舉有兩點不同:

1、迭代器允許呼叫者利用定義良好的語意在迭代期間從迭代器所指向的 collection 移除元素。

2、方法名稱都得到了改進。

其介面定義如下:

public interface Iterator {
  boolean hasNext();
  Object next();
  void remove();
}
登入後複製

其中:

Object next():傳回迭代器剛越過的元素的引用,回傳值是Object,需要強制轉換成自己需要的型別

hasNext():判斷容器內是否還有可供存取的元素

void remove():刪除迭代器剛越過的元素

對於我們而言,我們只一般只需使用next()、hasNext( ) 兩個方法即可完成迭代。如下:

for(Iterator it = c.iterator(); it.hasNext(); ) {
  Object o = it.next();
   //do something
}
登入後複製

前面闡述了Iterator 有一個很大的優點,就是我們不必知道集合的內部結果,集合的內部結構、狀態由Iterator 來維持,透過統一的方法hasNext()、next() 來判斷、取得下一個元素,至於具體的內部實現我們就不用關心了。但是身為一個合格的程式設計師我們非常有必要來弄清楚 Iterator 的實作。以下就 ArrayList 的原始碼進行分析分析。

二、各個集合的Iterator 的實現

下面就ArrayList 的Iterator 實現來分析,其實如果我們理解了ArrayList、Hashset、TreeSet 的資料結構,內部實現,對於他們是如何實現Iterator 也會胸有成竹的。因為 ArrayList 的內部實作採用數組,所以我們只需要記錄對應位置的索引即可,其方法的實作比較簡單。

2.1、ArrayList 的Iterator 實作

在ArrayList 內部首先是定義一個內部類別Itr,該內部類別實作Iterator 接口,如下:

private class Itr implements Iterator<E> {
//do something
}
登入後複製

所以透過使用ArrayList.iterator() 方法回傳的是Itr() 內部類,所以現在我們需要關心的就是Itr() 內部類別的實作:

在Itr 內部定義了三個int 型的變數:cursor 、lastRet、expectedModCount。其中cursor 表示下一個元素的索引位置,lastRet 表示上一個元素的索引位置

public Iterator<E> iterator() {
return new Itr();
}
登入後複製


從cursor、lastRet 定義可以看出,lastRet 一直比cursor 少一所以hasNext() 實作方法異常簡單,只需要判斷cursor 和lastRet 是否相等即可。

int cursor;
int lastRet = -1;
int expectedModCount = modCount;
登入後複製

對於 next() 實現其實也是比較簡單的,只要返回 cursor 索引位置處的元素即可,然後修改 cursor、lastRet 即可

public boolean hasNext() {
return cursor != size;
}
登入後複製

checkForComodification() 主要用来判断集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过。modCount 用于记录 ArrayList 集合的修改次数,初始化为 0,,每当集合被修改一次(结构上面的修改,内部update不算),如 add、remove 等方法,modCount + 1,所以如果 modCount 不变,则表示集合内容没有被修改。该机制主要是用于实现 ArrayList 集合的快速失败机制,在 Java 的集合中,较大一部分集合是存在快速失败机制的,这里就不多说,后面会讲到。所以要保证在遍历过程中不出错误,我们就应该保证在遍历过程中不会对集合产生结构上的修改(当然 remove 方法除外),出现了异常错误,我们就应该认真检查程序是否出错而不是 catch 后不做处理。

final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
登入後複製

对于 remove() 方法的是实现,它是调用 ArrayList 本身的 remove() 方法删除 lastRet 位置元素,然后修改 modCount 即可。

public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
登入後複製

以上所述是小编给大家介绍的Java集合Iterator迭代的实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对PHP中文网的支持!

更多Java集合Iterator迭代的实现方法相关文章请关注PHP中文网!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名構建查詢條件? 使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名構建查詢條件? Apr 19, 2025 pm 09:51 PM

在使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名以構建查詢條件,是一個常見的難題。本文將針...

See all articles