java迭代器删除两个_两个迭代器的故事
java迭代器刪除兩個(gè)
當(dāng)您查看最流行的Java面試問題時(shí),您可能會遇到有關(guān)故障快速和故障安全迭代器的問題:
故障快速迭代器和故障安全迭代器之間有什么區(qū)別?
簡化的答案是:
如果在迭代過程中修改了集合,則快速失敗迭代器將引發(fā)ConcurrentModificationException ,但不會失敗保護(hù)。
盡管這完全有道理,但不清楚訪調(diào)員的故障安全含義。 對于迭代器,Java規(guī)范未定義此術(shù)語。 但是,有四種同時(shí)進(jìn)行修改的策略。
并發(fā)修改
首先,讓我們定義什么是并發(fā)修改。 例如,當(dāng)我們有一個(gè)來自集合的活動迭代器并且對該集合進(jìn)行了某些更改,但它們不是來自我們的迭代器時(shí),會發(fā)生并發(fā)修改。 最明顯的例子是當(dāng)我們有多個(gè)線程時(shí)–一個(gè)線程正在迭代,第二個(gè)線程在同一集合中添加或刪除元素。 但是,當(dāng)我們在單線程環(huán)境中工作時(shí),我們也可以獲取ConcurrentModificationException :
List<String> cities = new ArrayList<>(); cities.add(“Warsaw”); cities.add(“Prague”); cities.add(“Budapest”);Iterator<String> cityIterator = cities.iterator(); cityIterator.next(); cities.remove(1); cityIterator.next(); // throws ConcurrentModificationException不及格
上面的代碼段是快速失敗迭代器的示例。 如您所見,一旦我們嘗試從迭代器中獲取第二個(gè)元素,就會引發(fā)ConcurrentModificationException 。 迭代器如何知道創(chuàng)建集合后是否對其進(jìn)行了修改? 您可能在集合中有一個(gè)時(shí)間戳,例如lastModified 。 創(chuàng)建迭代器時(shí),需要復(fù)制該字段并將其存儲在迭代器對象中。 然后,無論何時(shí)調(diào)用next()方法, lastModified需要將集合中的lastModified與迭代器中的副本進(jìn)行比較。 例如,可以在ArrayList實(shí)現(xiàn)中找到非常相似的方法。 有一個(gè)modCount實(shí)例變量,其中包含對列表進(jìn)行的修改次數(shù):
final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException(); }值得一提的是,快速失敗迭代器是在盡力而為的基礎(chǔ)上工作的-無法保證如果存在并發(fā)修改,則會拋出ConcurrentModificationException ,因此我們不應(yīng)該依賴該行為-而是應(yīng)將其用于檢測錯(cuò)誤。 大多數(shù)非并行集合都提供快速失敗的迭代器。
弱一致性
java.util.concurrent包中的大多數(shù)并發(fā)集合(例如ConcurrentHashMap和most Queues )都提供了弱一致性的迭代器。 文檔中對它的含義進(jìn)行了很好的解釋:
- 他們可能會與其他操作同時(shí)進(jìn)行
- 他們永遠(yuǎn)不會拋出ConcurrentModificationException
- 它們被保證可以遍歷在構(gòu)造時(shí)已經(jīng)存在的元素一次,并且可以(但不保證)反映出構(gòu)造后的任何修改。
快照
在此策略中,從創(chuàng)建迭代器的那一刻起,迭代器就與集合的狀態(tài)相關(guān)聯(lián)-我們的集合快照。 對初始集合所做的任何更改都會創(chuàng)建基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)的新版本。 當(dāng)然,我們的快照是不變的,因此它不反映在創(chuàng)建迭代器之后對集合所做的任何更改。 這是一種古老的好的寫時(shí)復(fù)制(COW)技術(shù)。 它完全解決了并發(fā)修改問題,因此不會引發(fā)ConcurrentModificationException 。 此外,迭代器不支持元素更改操作。 寫入時(shí)復(fù)制集合通常太昂貴而無法使用,但是如果突變發(fā)生的次數(shù)顯著減少,遍歷遍歷次數(shù)可能是個(gè)好主意。 示例為CopyOnWriteArrayList和CopyOnWriteArraySet 。
未定義
未定義的行為可以在傳統(tǒng)集合中找到,例如Vector和Hashtables 。 它們都具有具有快速失敗行為的標(biāo)準(zhǔn)迭代器,但是它們還公開了Enumeration接口的實(shí)現(xiàn),該接口在定義并發(fā)修改時(shí)不定義行為。 您可能會看到某些項(xiàng)目被重復(fù)或跳過,甚至飛來飛去的一些怪異異常。 最好不要玩這個(gè)野獸!
翻譯自: https://www.javacodegeeks.com/2017/11/tale-two-iterators.html
java迭代器刪除兩個(gè)
總結(jié)
以上是生活随笔為你收集整理的java迭代器删除两个_两个迭代器的故事的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jsf 项目_您将在下一个项目中使用JS
- 下一篇: Telegram、TON 基金会宣布与腾