Jetty.util.MultiMap抛出ConcurrentModificationException

时间:2017-08-10 06:19:48

标签: java jetty

我有一个名为clientPrinterConnections的多图,它以多种方式将打印机名称映射到SocketConnections。当我关闭SocketConnection时,我想删除使用它的每个条目。我认为Multimap实现了ConcurrentMap(它看起来像是在8.0.0但不是9.0.0)所以我这么做了。

    for (Map.Entry<String, List<SocketConnection>> e: clientPrinterConnections.entrySet()) {
        if (e.getValue().contains(connection)) {
            clientPrinterConnections.removeValue(e.getKey(),connection);
        }
    }

它最终无法正常工作,并且会抛出ConcurrentModificationException。由于需要removeValue调用,我无法真正使用迭代器。

    Iterator iter = clientPrinterConnections.entrySet().iterator();
    while(iter.hasNext()) {
        Map.Entry<String, List<SocketConnection>> pair = (Map.Entry)iter.next();
        if (pair.getValue().contains(connection)) {
            //this deletes all connections to the specific printer
            iter.remove();
            //this throws the same exception as before
            clientPrinterConnections.removeValue(pair.getKey(),connection);
        }
    }

我可以像这样编译一个要删除的东西列表,

    ArrayList<String> itemsToDelete = new ArrayList();
    for (Map.Entry<String, List<SocketConnection>> e: clientPrinterConnections.entrySet()) {
        if (e.getValue().contains(connection)) {
            itemsToDelete.add(e.getKey());
        }
    }
    for (String s: itemsToDelete){
        clientPrinterConnections.removeValue(s,connection);
    }

但这看起来很混乱。有没有更优雅的方式来做到这一点?我可以想象一些情况,只是编译列表不是一个充分的解决方案。

2 个答案:

答案 0 :(得分:1)

由于它是引发异常的Iterator,因此任何修改都需要通过它。由于您没有特殊的MultiMapIterator,因此编制删除列表是您最好的选择。

答案 1 :(得分:0)

使用临时地图

        Map<String, List<SocketConnection>> tempMap = new HashMap<String, List<SocketConnection>>();

        for (Map.Entry<String, List<SocketConnection>> e: clientPrinterConnections.entrySet()) {
          if (e.getValue().contains(connection)) {
            tempMap.put(e.getKey(),e.getValue());
          }
        }

        clientPrinterConnections.clear();
        clientPrinterConnections.putAll(tempMap);