猿问

ConcurrentHashMap 的值抛出 NullPointerException

我正在维护使用ConcurrentHashMap.


其他方法中有add和remove的操作。


在下面的代码中,在从地图中收集了一些值后的某个时刻,它NullPointerException在执行时抛出synchronize(value)。


public class MyClass{


    private final Map<MyObj, Map<String, List<String>>> conMap = new ConcurrentHashMap<>();


    //...


    public void doSomthing((MyObj id){

        List<Map<String, List<String>>> mapsList = new LinkedList<>();

        for(MyObj objId: conMap.keySet()){              

            if(objId.key1.equals(id.key1)){

                mapsList.add(conMap.get(objId));

            }

        }


        for(Map<String, List<String>> map: mapsList){

            synchronized(map){                   // <-- NullPointerException here

                //...

            }

    }


    //...


}

我有一种感觉,也许在第一个循环的迭代过程中,记录被删除了。当行:


mapsList.add(conMap.get(objId));

正在执行,objId不再存在并mapsList添加 null,结果,在第二个循环期间NullPoinerException被抛出。


还有其他原因可以得到这个例外吗?


神不在的星期二
浏览 240回答 1
1回答

慕码人2483693

您已经爱上了 Check-Then-Act 反模式。它意味着检查条件(如密钥的存在),然后对其采取行动(如调用get),忽略条件可能在其间发生变化的可能性。因此,您在迭代时遇到了一个特定的键conMap.keySet(),但在您调用conMap.get(objId)时,该键可能不再位于映射中,返回时会报告这一点null。强烈建议使用具有合适hashCode/equals实现的键类型,这样您就无需遍历整个地图来查找匹配项,而是可以使用单个get(id).但是,当您必须遍历映射并需要值时,请遍历条目集而不是键集。public void doSomething(MyObj id){&nbsp; &nbsp; // see https://stackoverflow.com/q/322715/2711488&nbsp; &nbsp; List<Map<String, List<String>>> mapsList = new ArrayList<>();&nbsp; &nbsp; for(Map.Entry<MyObj, Map<String, List<String>>> e: conMap.entrySet()){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; if(e.getKey().key1.equals(id.key1)){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mapsList.add(e.getValue());&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; for(Map<String, List<String>> map: mapsList){&nbsp; &nbsp; &nbsp; &nbsp; synchronized(map) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //...&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
随时随地看视频慕课网APP

相关分类

Java
我要回答