2012-06-27 6 views
5

Ich bin interessiert, wenn es ein Framework gibt, das eine Sammlung implementiert, die das folgende Verhalten hätte.Java-Sammlung zum Hinzufügen und Entfernen während der Iteration


nehme an, es enthält zu Beginn: [1, 2, 3]

  • I iterieren es (einen Iterator verwendet wird) und erreichen Element 2 nun I 4 zum Ende hinzuzufügen (die Sammlung wird jetzt sei [1, 2, 3, 4]).
  • jetzt erstelle ich einen neuen Iterator und die Sammlung iterieren, was zu [1, 2, 3, 4]
  • ich mit dem ersten Iterator weiter laufen und es wird mir geben nur 3 und zurück
  • jetzt das Zurücksetzen Der erste Iterator gibt mir [1, 2, 3, 4] (ähnlich wie beim Erstellen eines neuen).

Gleiches sollte für die Entfernung von Elementen gelten. Wenn ich 3 entferne, anstatt hinzuzufügen, sollte der zweite Iterator mir [1, 2] geben, während der erste I noch 3 und das Ende geben wird.


Also, wenn ich bekommen und Iterator will ich es mir die Sammlung geben, die ich hatte, als ich den Iterator erstellt (auch wenn ich es iterieren später, am ich ein wenig und später weiterlaufen), wenn ich die Reset Iterator, es wird Müll gesammelt, es wird auf die neuesten Versionen aktualisiert, und ich sollte in der Lage sein, mehrere Iterator-Instanzen zu verschiedenen Zeiten erstellt zu haben, die verschiedene Versionen abhängig vom Inhalt des Arrays ergeben, wenn der Iterator erstellt wurde.

Ich würde es gut mit mehreren Threads arbeiten und vorzugsweise eine effiziente Implementierung haben.

Kennt jemand irgendeine Implementierung einer solchen Sammlung, oder muss ich es selbst implementieren?

Antwort

6

Was Sie beschreiben, sieht sehr ähnlich wie CopyOnWriteArrayList Werke:

  • sobald Sie Iterieren starten, können Sie die Sammlung ändern (von einem anderen Thread einschließlich), ohne die Iteration
  • zu beeinflussen
  • wenn Sie einen neuen Iterator erstellen es wird
  • an der Erstellungszeit auf der Sammlung basiert
  • ist es Thread-sicher

Einfaches Beispiel unter dem folgenden outpu t:

Iterator 1 - 1
4 hinzugefügt wurde
Iterator 2 - 1
Iterator 2 - 2
Iterator 2 - 3
Iterator 2 bis 4
Iterator 1 bis 2
Iterator 1 - 3

public static void main(String[] args) throws InterruptedException { 
    final List<Integer> list = new CopyOnWriteArrayList<Integer>(); 
    list.addAll(Arrays.asList(1, 2, 3)); 
    new Thread(new Runnable() { 

     @Override 
     public void run() { 
      for (Integer i : list) { 
       System.out.println("Iterator 1 - " + i); 
       try { 
        Thread.sleep(10); 
       } catch (InterruptedException e) {} 
      } 
     } 
    }).start(); 
    Thread.sleep(10); 
    list.add(4); 
    System.out.println("4 has been added"); 
    for (Integer i : list) { 
     System.out.println("Iterator 2 - " + i); 
    } 

} 
+0

Gibt es eine neue Kopie der Sammlung auf Änderung (intern) erstellen? Oder wird es effizienter umgesetzt? – Razvi

+1

Ja wie im Javadoc beschrieben: "Alle mutativen Operationen (hinzufügen, setzen usw.) werden implementiert, indem eine neue Kopie des zugrunde liegenden Arrays erstellt wird." – assylias

+0

Das Verhalten sieht aus, als was ich brauche. Aber die Sammlung wird einiges enthalten. Iteratoren werden häufig darauf erstellt, aber ich glaube, dass Änderungen seltener sind (so dass Kopien bei Änderung möglicherweise nicht zu viel Leistungsverlust verursachen). – Razvi

7

java.util.concurrent.CopyOnWriteArrayList wird sich so verhalten, außer dass keine Java-Sammlung "Iteratoren" zurückgesetzt hat - aber das Abrufen eines neuen Iterators anstelle des Zurücksetzens hat den Effekt, den Sie hier anfordern.

2

Sie können die ImmutableCollections aus der Guava-Bibliothek verwenden.

Die zurück ImmutableList ist häufig - nicht immer, aber häufig - eine Konstantdraufsicht, anstatt eine explizite Kopie. Das heißt, es ist oft schlauer als Ihre durchschnittliche Liste - zum Beispiel wird es die effiziente enthält Methoden der Sammlung Backing verwenden.

3

Sie Gebrauch von java.util.concurrent.CopyOnWriteArrayList<E> machen könnten

Laut Dokumentation:

eine Thread-sichere Variante von Arraylist, in dem alle mutative Operationen (hinzuzufügen, setzen, und so weiter) sind implementiert, indem eine neue Kopie des zugrundeliegenden Arrays erstellt wird.

Es ist teuer, aber Thread Safe.

Dies normalerweise zu teuer ist, aber als Alternativen effizient sein kann, wenn in beträchtlichem Ausmaß outnumber Mutationen Traversal Operationen und nützlich ist, wenn Sie nicht können oder wollen nicht Querungen synchronisieren, aber müssen Störungen auszuschließen unter gleichzeitigen Threads. Die "snapshot" Stil-Iterator-Methode verwendet einen Verweis auf den Zustand des Arrays unter den Punkt, an dem der Iterator erstellt wurde.

Da die Iteration eine Art Momentaufnahme erfolgt über die Operationen (remove, set und add) auf Iterator sind selbst nicht unterstützt.

0

Javolution haben Threadsicheres FastMap

Verwandte Themen