簡體   English   中英

克服 HashMap 中的快速失敗迭代器的方法

[英]Way to overcome fail-fast iterator in HashMap

在競爭性編程中,我正在解決一個給定的問題 - 給定一個非負整數數組nums和一個目標總和S ,我們必須找出從給定數字的總和中獲得目標總和的方法數量(其中每個nums[i]可以被視為nums[i]-nums[i]

雖然我遇到了一些主要依賴於使用數組直接訪問表的解決方案(假設數字之和不能超過 1000),但我嘗試使用 HashMap 來減少所需空間。 我的代碼如下 -

    public int findTargetSumWays(int[] nums, int S) {
        Map<Integer, Integer> dp = new HashMap();
        dp.put(nums[0], 1);
        dp.put(-nums[0], dp.getOrDefault(-nums[0], 0) + 1);
        
        for (int i=1; i<nums.length; i++) {
            for (Integer sum : dp.keySet()) {
                dp.put(sum+nums[i], dp.getOrDefault(sum+nums[i], 0) + 1);
                dp.put(sum-nums[i], dp.getOrDefault(sum-nums[i], 0) + 1);
            }
        }
        return dp.get(S);
    }

但是我在運行代碼時遇到了 ConcurrentModificationException 。 我試圖找到這個問題。 盡管我在迭代中得到了一些概念上的理解,Collections 的視圖不能在結構上進行修改,但我無法弄清楚如何找到解決方法。

是不是不可能使用 HashMap(或任何動態數據結構)的解決方案? 任何幫助表示贊賞。

for (Integer sum : dp.keySet()) {
  dp.put(sum+nums[i], dp.getOrDefault(sum+nums[i], 0) + 1);
  // ...
}

如果sum + nums[i]不是 map 中已經存在的鍵,則會導致 map 的結構修改:也就是說,您正在添加一個新的鍵/值對。

Javadoc 中所述

所有此類的“集合視圖方法”返回的迭代器都是快速失敗的:如果 map 在創建迭代器后的任何時間進行結構修改,除了通過迭代器自己的 remove 方法之外,迭代器將拋出 ConcurrentModificationException .

(如果密鑰已經在 map 中,您只需修改與該密鑰關聯的值,這樣就可以了)。

解決這個問題的最簡單方法是通過將元素復制到例如列表中來獲取要迭代的鍵的快照:

for (Integer sum : new ArrayList<>(dp.keySet())) {

現在,您正在迭代列表,而不是地圖的鍵集,因此您可以自由地在該循環內從結構上修改 map。


與異常問題不同,您的put/getOrDefault更簡單地寫為:

// dp.put(sum+nums[i], dp.getOrDefault(sum+nums[i], 0) + 1);
// becomes
dp.merge(sum+nums[i], 1, Integer::sum);

ConcurrentModificationException的原因是您在以下循環中迭代dp.keySet()時正在修改dp的鍵:

for (Integer sum : dp.keySet()) {
    dp.put(sum+nums[i], dp.getOrDefault(sum+nums[i], 0) + 1);
    dp.put(sum-nums[i], dp.getOrDefault(sum-nums[i], 0) + 1);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM