Java中迭代器如何工作

簡(jiǎn)書 賈小強(qiáng)
轉(zhuǎn)載請(qǐng)注明原創(chuàng)出處铝宵,謝謝首懈!

你將在面試中被問這個(gè)問題很多次,比如垂睬,在Java中迭代器(Iterator)如何工作的媳荒,怎么刪除List中的元素抗悍?什么時(shí)候拋出IllegalStateException? 什么時(shí)候在會(huì)拋出ConcurrentModificationException? Iterator和ListIterator之間的區(qū)別?

什么時(shí)候拋出IllegalStateException

Java迭代器接口定義如下

public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove();
}

hasNext() 如果仍有元素可以迭代,則返回 true钳枕。
next() 返回迭代的下一個(gè)元素缴渊。
remove() 從迭代器指向的 collection 中移除迭代器返回的最后一個(gè)元素(可選操作)。每次調(diào)用 next 只能調(diào)用一次此方法鱼炒。否則拋出IllegalStateException衔沼,如下

Iterator<Integer> iterator1=arrayList.iterator();

iterator1.next();
iterator1.remove();
iterator1.remove();  // throws IllegalStateException

正確的方式應(yīng)該是:

Iterator<Integer> iterator1=arrayList.iterator();

iterator1.next();
iterator1.remove();
iterator1.next();
iterator1.remove();

什么時(shí)候拋出ConcurrentModificationException

在Java中,當(dāng)你實(shí)例化一個(gè)迭代器昔瞧,當(dāng)你修改集合的時(shí)候指蚁,它就會(huì)計(jì)數(shù)。如果迭代器檢測(cè)到你用不是用它修改了集合(比如同一個(gè)集合的另一個(gè)迭代器)自晰,它不能保證操作的正確性凝化,比如一個(gè)一個(gè)迭代器指向另一個(gè)迭代器剛剛刪除的元素前面,現(xiàn)在這個(gè)迭代器就是無效的酬荞,而且不應(yīng)該再被使用搓劫,迭代器的設(shè)計(jì)使它能夠檢測(cè)到這種修改。如果發(fā)現(xiàn)那么拋出ConcurrentModificationException混巧。

ArrayList<Integer> arrayList=new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
        
Iterator<Integer> iterator1=arrayList.iterator();
Iterator<Integer> iterator2=arrayList.iterator();

iterator1.next();
iterator1.remove();
iterator2.next(); // throws ConcurrentModificationException

由于iterator2檢測(cè)出了這個(gè)List被從外部修改了枪向,所以對(duì)iterator2.next的調(diào)用拋出ConcurrentModificationException

ArrayList的方法有一個(gè)計(jì)數(shù)器的modcount,聲明為:

protected transient int modCount = 0;

當(dāng)你用一個(gè)ArrayList創(chuàng)建一個(gè)Iterator/ListIterator咧党,這個(gè)modCount被用來初始化Iterator對(duì)象中的一個(gè)叫expectedModCount的字段

int expectedModCount = modCount;

在ArrayList上的任何操作(不使用迭代器實(shí)例)將增加modCount秘蛔。迭代器的所有方法執(zhí)行前都講檢查modCount == expectedModCount。如果它們不相等凿傅,則拋出異常缠犀。

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

Iterator和ListIterator之間的區(qū)別

先看如下類層次關(guān)系

可以發(fā)現(xiàn)實(shí)現(xiàn)Collection接口的所有集合都可以產(chǎn)生Iterator
而只有實(shí)現(xiàn)List接口的集合(比如ArrayList,LinkedList聪舒,Vector辨液,Stack)可以產(chǎn)生ListIterator

原因在于使用Iterator,比如計(jì)算集合元素的總是或者符合某種條件的元素個(gè)數(shù)這種和順序無關(guān)的并沒有問題箱残,但因?yàn)榈鳎↖terator和ListIterator)描述了元素的位置關(guān)系滔迈,而add方法又依賴于這種位置關(guān)系,那么比如對(duì)于Set這種完全無序的集合Iterator提供add方法就不合適了(Set集合本身是根據(jù)元素的hashCode來決定元素的位置被辑,而如果直接用迭代器add燎悍,將一個(gè)元素直接添加到上一個(gè)元素的后面,那將破壞哈希機(jī)制)盼理,于是分出了ListIterator谈山,專門針對(duì)有序集合提供add方法

我希望以上的解釋能幫助你回答這個(gè)面試問題。

Happy Learning !!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末宏怔,一起剝皮案震驚了整個(gè)濱河市奏路,隨后出現(xiàn)的幾起案子畴椰,更是在濱河造成了極大的恐慌,老刑警劉巖鸽粉,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斜脂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡触机,警方通過查閱死者的電腦和手機(jī)帚戳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來儡首,“玉大人片任,你說我怎么就攤上這事〗范妫” “怎么了蚂踊?”我有些...
    開封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長笔宿。 經(jīng)常有香客問我犁钟,道長,這世上最難降的妖魔是什么泼橘? 我笑而不...
    開封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任涝动,我火速辦了婚禮,結(jié)果婚禮上炬灭,老公的妹妹穿的比我還像新娘醋粟。我一直安慰自己,他們只是感情好重归,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開白布米愿。 她就那樣靜靜地躺著,像睡著了一般鼻吮。 火紅的嫁衣襯著肌膚如雪育苟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天椎木,我揣著相機(jī)與錄音违柏,去河邊找鬼。 笑死香椎,一個(gè)胖子當(dāng)著我的面吹牛漱竖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播畜伐,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼馍惹,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起讼积,我...
    開封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤肥照,失蹤者是張志新(化名)和其女友劉穎脚仔,沒想到半個(gè)月后勤众,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鲤脏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年们颜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猎醇。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡窥突,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出硫嘶,到底是詐尸還是另有隱情阻问,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布沦疾,位于F島的核電站称近,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏哮塞。R本人自食惡果不足惜刨秆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望忆畅。 院中可真熱鬧衡未,春花似錦、人聲如沸家凯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绊诲。三九已至送粱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驯镊,已是汗流浹背葫督。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留板惑,地道東北人橄镜。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像冯乘,于是被迫代替她去往敵國和親洽胶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • java筆記第一天 == 和 equals ==比較的比較的是兩個(gè)變量的值是否相等,對(duì)于引用型變量表示的是兩個(gè)變量...
    jmychou閱讀 1,504評(píng)論 0 3
  • Java源碼研究之容器(1) 如何看源碼 很多時(shí)候我們看源碼, 看完了以后經(jīng)常也沒啥收獲, 有些地方看得懂, 有些...
    駱駝騎士閱讀 996評(píng)論 0 22
  • 1.Java集合框架是什么?說出一些集合框架的優(yōu)點(diǎn)? 每種編程語言中都有集合姊氓,最初的Java版本包含幾種集合類:V...
    hutuxiaogui閱讀 677評(píng)論 0 10
  • 1.Java集合框架是什么丐怯?說出一些集合框架的優(yōu)點(diǎn)? 每種編程語言中都有集合翔横,最初的Java版本包含幾種集合類:V...
    獨(dú)念白閱讀 777評(píng)論 0 2
  • 1.Java集合框架是什么读跷?說出一些集合框架的優(yōu)點(diǎn)?每種編程語言中都有集合禾唁,最初的Java版本包含幾種集合類:Ve...
    yjaal閱讀 1,179評(píng)論 1 10