java迭代器cas,java提高篇(三十)-Iterator - Java 技術驛站-Java 技術驛站

迭代對于我們搞Java的來說絕對不陌生。我們常常使用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 list = new ArrayList();

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,需要強制轉換成自己需要的類型

boolean 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 {

//do something

}

而ArrayList的iterator()方法實現:

public Iterator iterator() {

return new Itr();

}

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

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

int cursor;

int lastRet = -1;

int expectedModCount = modCount;

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

public boolean hasNext() {

return cursor != size;

}

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

public E next() {

checkForComodification();

int i = cursor; //記錄索引位置

if (i >= size) //如果獲取元素大于集合元素個數,則拋出異常

throw new NoSuchElementException();

Object[] elementData = ArrayList.this.elementData;

if (i >= elementData.length)

throw new ConcurrentModificationException();

cursor = i + 1; //cursor + 1

return (E) elementData[lastRet = i]; //lastRet + 1 且返回cursor處元素

}

checkForComodification()主要用來判斷集合的修改次數是否合法,即用來判斷遍歷過程中集合是否被修改過。在java提高篇(二一)-----ArrayList中已經闡述了。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();

}

}

這里就對ArrayList的Iterator實現講解到這里,對于Hashset、TreeSet等集合的Iterator實現,各位如果感興趣可以繼續研究,個人認為在研究這些集合的源碼之前,有必要對該集合的數據結構有清晰的認識,這樣會達到事半功倍的效果!!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/529827.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/529827.shtml
英文地址,請注明出處:http://en.pswp.cn/news/529827.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysqldb mysql config,安裝mysqldb python界面時找不到mysql_config

mySQLdb是一個用于mysql的python界面&#xff0c;但它不是mysql本身。 顯然mySQLdb需要命令“mysql_config”&#xff0c;所以你需要先安裝。你能否確認你是否通過從shell運行“mysql”來安裝mysql本身&#xff1f; 這應該給你一個“mysql&#xff1a;command not found”以外的…

kfcm算法matlab實現,KFCM算法分析

function [center, U, obj_fcn] KFCMClust(data, cluster_n, kernel_b,options)% FCMClust.m 采用模糊C均值對數據集data聚為cluster_n類%% 用法&#xff1a;% 1. [center,U,obj_fcn] KFCMClust(Data,N_cluster,kernel_b,options);% 2. [center,U,obj_fcn] KFCMClus…

matlab中的terminator模塊,2.2 Ground 及 Terminator模塊

課時&#xff1a;117節課時長&#xff1a;20.1小時課級&#xff1a;中級提高simulink是matlab中的一種可視化仿真工具&#xff0c; 是一種基于matlab的框圖設計環境&#xff0c;是實現動態系統建模、仿真和分析的一個軟件包&#xff0c;被廣泛應用于線性系統、非線性系統、數字…

matlab 柯西黎曼方程,【判斷題】柯西-黎曼方程成立是函數解析的必要條件.

參考答案如下判斷【判斷題】核糖體的沉降系數等于大小亞基沉降系數的總和。題柯【其它】We ______________________________________ (投入到各項校園課外活動中) on campus.西黎【單選題】起動機與蓄電池的連接線蓄電池與車架的搭鐵線則采用( )。 (2.0分)曼方【簡答題】作業選…

取整函數php,php取整函數三個例子

本節內容&#xff1a;php取整函數用法1&#xff0c;php取整函數 ceil -- 取最大整數float ceil ( float value )返回不小于 value 的下一個整數&#xff0c;value 如果有小數部分則進一位。ceil() 返回的類型仍然是 float&#xff0c;因為 float 值的范圍通常比 integer 要大。…

python執行過程打印,如何在pytest運行過程中看到正常的打印輸出?

喬在接受的答案中提出了一個評論 &#xff0c;他問道&#xff1a;有沒有辦法打印到控制臺并捕獲輸出&#xff0c;以便它顯示在junit報告中&#xff1f;在UNIX中&#xff0c;這通常被稱為開球 。 理想情況下&#xff0c;開球而不是捕捉將是py.test默認。 非理想情況下&#xff0…

cfar恒虛警matlab實現,一種用于距離副瓣抑制的自適應恒虛警方法與流程

本發明涉及脈沖壓縮雷達數字信號處理技術領域。背景技術&#xff1a;在傳統的真空管體制雷達中&#xff0c;由于發射占空比受限&#xff0c;通過設計較低的雷達重復發射頻率實現遠距離的目標探測&#xff0c;但由于發射的是簡單的脈沖調制波形&#xff0c;重復頻率降低和脈寬加…

修改oracle數據連接數據庫,如何修改oracle數據庫的連接數

如何修改oracle數據庫的連接數查詢數據庫當前進程的連接數&#xff1a;select count(*) from v$process;查看數據庫當前會話的連接數&#xff1a;elect count(*) from v$session;查看數據庫的并發連接數&#xff1a;select count(*) from v$session where statusACTIVE;查看當前…

oracle導出中文utf8亂碼,ORACLE導入導出后發生中文亂碼的原因及解決辦法

從數據庫服務器上使用exp導出時顯示如下&#xff1a;[oraclekf15-1]:/users/oracle>$ exp username/passwdkf15-1/i1000 tablestable_name filetable_name_unix.dmp satisticsnone buffer1000000Export: Release 10.2.0.4.0 - Production on 星期四 8月 26 16:37:08 2010Cop…

基于matlab的圖解粒度參數計算,基于MATLAB的圖解粒度參數計算

摘要粒度特征是沉積物的基本特征之一。計算沉積物粒度參數的方法主要有矩法和圖解法兩種&#xff0c;其中圖解法必須通過手工作圖求累積曲線&#xff0c;是一項相當繁雜的勞動&#xff0c;不利于計算大量樣品。文中提出的方法將圖解求沉積物樣品的累積曲線百分位數的過程轉化為…

oracle判斷數據出現交叉,Oracle!你必須要知道的Knowledge points(一)

一、入門oracle有四個用戶&#xff0c;分別為sys、system、sysman和scott,其中sys是oracle權限最高的用戶&#xff0c;類似于Linux系統的root&#xff0c;scott是示例用戶&#xff0c;上課就以這個用戶里的三張員工表empno、dept、salgrade作為示例來授課。啟動服務1. 快捷鍵ct…

php上傳中文圖片,用PHP處理圖片文件的上傳

這篇文章主要介紹了關于用PHP處理圖片文件的上傳&#xff0c;有著一定的參考價值&#xff0c;現在分享給大家&#xff0c;有需要的朋友可以參考一下1.html文件form表單注意。enctype屬性代碼&#xff1a;<?php require(../../public/common/config.php);$sqlClass "s…

nodejs+php+aes加密解密,php,crypto_php與nodejs的加密數據互通,php,crypto,node.js - phpStudy...

php與nodejs的加密數據互通nodejs的加密解密代碼示例如下&#xff1a;#!/usr/bin/env nodevar crypto require(crypto);//解密function decode(cryptkey, iv, secretdata) {vardecipher crypto.createDecipheriv(aes-256-cbc, cryptkey, iv),decoded decipher.update(secret…

360 php offer,審批終于通過了,從面試到拿到奇虎360的offer已經失…

審批終于通過了&#xff0c;從面試到拿到奇虎360的offer已經失業兩周了( ?????)?- - -?&#xfeff;小運營大太陽&#xff1a;沾沾喜氣程序猿.南蘭&#xff1a;沾沾喜氣360員工&#xff1a;歡迎來到酒仙橋第一養老院美團點評員工&#xff1a;[害羞]沾沾喜氣盜圣白展堂&a…

linux中的進程權限是,Linux中權限,進程,服務的簡單操作

1.權限存在意義- rw-r-r-r-- 1 root root 216 May 12 2017 /mnt/rht[1] [2] [3] [4] [5] [6] [7] [8][1] 文件類型-普通文件d目錄l軟鏈接ssocketc文件權限[2] 文件權限rw-|r--|r--u g ouuserggroupoo…

linux 中斷 進程,linux中斷分上下部分原因

中斷處理程序在處理中斷時起到了關鍵作用&#xff0c;也是一個中斷程序必不可少的部分。不過&#xff0c;現如今的中斷處理流程都會分為兩部分&#xff1a;上半部分(top half)和下半部分(bottom half)。為什么要將一個中斷分為如此兩部分&#xff1f;下面的幾個經典原因可以很好…

linux 運行eclipse,解決Linux下Eclipse啟動錯誤

下載Eclipse后一打開就報錯&#xff1a;JVM terminated. Exit code-1-Xms40m-Xmx256m-XX:MaxPermSize256m-Djava.class.path/usr/local/eclipse/plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar-os linux-ws gtk-arch x86-showsplash /usr/local/eclipse//pl…

linux家庭云服務器,linux服務器云(linux家用云服務器)

可以。注&#xff1a;云服務器有Linux版本&#xff0c;實際上就是Linux在本地環境放到了云上公網環境中&#xff0c;其它操作都是一樣的。云主機是集群服務器開發出的虛擬的機器&#xff0c;所以&#xff0c;這個因素不用考慮就問題不大。需要linux系統直接在預裝系統安裝就可以…

linux13位時間戳,Kotlin 處理Linux時間戳

思路1. 獲取時間可以采用的方式有直接獲取系統時間System.currentTimeMillis()或者使用Calendar類獲取時間2. 處理時間在使用Calendar時&#xff0c;可以直接由Calendar的set方法對于時間進行設置由于Calendar的時間格式并不是我們希望得到的Linux時間戳格式&#xff0c;所以我…

linux腳本done報錯,linux – 如何在shell腳本中處理錯誤/異常?

下面是我在bash中執行的腳本.它工作正常.fileexist0for i in $( ls /data/read-only/clv/daily/Finished-HADOOP_EXPORT_&processDate#.done); domv /data/read-only/clv/daily/Finished-HADOOP_EXPORT_&processDate#.done /data/read-only/clv/daily/archieve-wip/fil…