[英]Java: What is the advantage of using HashMap iterator over ConcurrentHashMap?
我有一個使用 Map 的單線程程序,其中在迭代時將一項一項刪除。 我已經讀過可以在這里使用迭代器來避免ConcurrentModificationException
但為什么不使用 ConcurrentHashMap 來代替它似乎更干凈?
我的代碼:
private final Map<Integer, Row> rowMap;
.....
private void shutDown() {
for (Integer rowNumber : rowMap.keySet()) {
closeRow(rowNumber)
deleteRow(rowNumber)
}
}
....
在 closeRow() 方法中:
private void closeRow(Integer rowNumber) {
Row row = rowMap.remove(rowNumber);
if (row != null) {
row();
}
}
deleteRow() 方法也類似。
對於我的場景,使用迭代器意味着將其聲明為 final,以便 closeRow() 和 deleteRow() 方法可以訪問它以將其刪除。 此外, iterator.remove() 方法不會返回要刪除的項目的值,這在我的情況下是必需的。
我的問題是,最有效的方法是什么,它不會拋出 ConcurrentModificationException? 是使用迭代器還是將 rowMap 設為 ConcurrentHashMap?
僅當它在線程之間共享時才使用ConcurrentHashMap
。
在單線程中,如果在使用迭代器時修改 object,則會引發CurrentModificationException
。
有兩種方法可以從集合中刪除元素,例如列表和 map。 一種是在集合上調用 remove。 另一種是使用迭代器。 但它們不能一起使用。 如果使用集合 object 的 remove 方法刪除元素,它將使迭代器的 state 無效。
List<Integer> list = new ArrayList(List.of(1,2,3,4,5));
Iterator<Integer> it = list.iterator();
list.remove(0);
while(it.hasNext()){
System.out.print(it.next());
}
這是一個例外:
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
at Main.main(Main.java:15)
這是一個相當簡單的迭代器模式。
Iterator<Map.Entry<Integer,Row>> it = rowMap.entrySet();
while (it.hasNext()) {
Map.Entry<Integer,Row> ent = it.next();
it.remove();
// ... do what you want with ent.getKey() and ent.getValue();
}
你可以。 事實上, Map
或ConcurentMap
並沒有像List
接口那樣提供迭代器。 但是您可以使用map.entrySet().iterator();
如果你這樣做,你會得到一個 concurrentModifcation 異常。
Map<Integer,Integer> map = new HashMap<>(Map.of(1,2,2,2,3,2,4,2,5,3,6,3,7,3));
for(int key : map.keySet()) {
map.put(key*10,4);
}
但在這里你不會
Map<Integer,Integer> map = new ConcurrentHashMap<>(Map.of(1,2,2,2,3,2,4,2,5,3,6,3,7,3));
for(int key : map2.keySet()) {
map2.put(key*10,4);
}
您可以以相同的方式刪除密鑰。 請注意, keySet()
返回鍵的視圖,因此您可以看到剛剛添加的一些(但可能不是全部)鍵。 我相信這個過程是非決定性的,因為它取決於鍵的 hash。
這是迭代器的方式。
Iterator<Entry<Integer,Integer>> iter= map.entrySet().iterator();
while(iter.hasNext()) {
iter.next();
iter.remove();
}
System.out.println(map); // prints {}
ConcurrentHashMaps
主要用於多線程環境,但您可以使用它們來避免並發修改異常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.