2017-08-10 5 views
0

Ich habe eine Multimap namens clientPrinterConnections, die Druckernamen SocketConnections auf viele Weise zuordnet. Wenn ich eine SocketConnection schließe, möchte ich jeden Eintrag löschen, der sie benutzt. Ich dachte, Multimap implementiert ConcurrentMap (es scheint, als ob es in 8.0.0, aber nicht in 9.0.0 getan hat), also habe ich es einfach gemacht.Jetty.util.MultiMap Throwing ConcurrentModificationException

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

Es endet das nicht funktioniert, und es wirft ein ConcurrentModificationException. Ich kann einen Iterator jedoch nicht wirklich verwenden, da ich einen removeValue-Aufruf benötige.

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); 
     } 
    } 

Ich kann nur eine Liste der Dinge kompilieren wie diese zu löschen,

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); 
    } 

aber das scheint chaotisch. Gibt es einen eleganteren Weg, dies zu tun? Ich kann mir Situationen vorstellen, in denen das Erstellen einer Liste keine ausreichende Lösung darstellt.

+0

Beachten Sie, dass 'ConcurrentModificationException' nichts mit Nebenläufigkeit zu tun hat, das heißt eine gleichzeitige Karte verwenden würde die Ausnahme nicht entfernen. – Kayaman

Antwort

1

Da es die Iterator ist, die die Ausnahme auslöst, müssen alle Änderungen durchlaufen werden. Da es keine speziellen MultiMapIterator gibt, zu denen Sie casten können, ist die Zusammenstellung einer Entfernungsliste die beste Wahl.

0

Verwenden Sie eine temporäre Karte,

 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); 
Verwandte Themen