2016-04-25 4 views
4

Ich habe den folgenden Code:Ist es sicher, eine Collections.swap() innerhalb einer Arraylist für eine Schleife zu machen?

private List<String> listOfStrings = new ArrayList<>(); 
listOfStrings.add("a"); 
listOfStrings.add("b"); 
listOfStrings.add("c"); 
listOfStrings.add("d"); 

for (String temp : listOfStrings) { 
    if (temp.equals("c")) { 
    Collections.swap(listOfStrings, 0, listOfStrings.indexOf(temp)); 
    } 
} 

Die Liste kann einfach nicht Liste der String sein, sondern könnte eine Liste der Objekte, die von der Klasse definiert, die ich geschrieben habe. Ich bin mir nicht sicher über den Tausch hier, ich sehe es kompiliert und läuft gut, aber ich weiß nicht, ob es hier sicher ist.

Hat jemand irgendwelche Vorschläge dazu? Wenn ich den Tausch machen muss. Ich plante, for (int i = 0; i < size; i++) zu verwenden, um zu iterieren und list.get(i) zu verwenden, um Einzelteil zu erhalten, aber ich denke, dass es nicht gute Idee ist, list.get(i) auf einer arraylist zu verwenden?

Jede Hilfe wird geschätzt werden !! Danke im Voraus!!

+0

Werfen Sie einen Blick hier: http://stackoverflow.com/questions/15963549/arraylist-swap-elements –

+0

was meinst du mit „es ist hier sicher“? –

+0

sind Sie besorgt über simplicomodificationException hier? – Abhishek

Antwort

0
swap(List<?> list, int i, int j) 

Take list und zwei Indizes als Argument, um es in for-Schleife zu setzen sollte kein Problem sein.

intern Swap-Verfahren Sie wie folgt:

final List l = list; 
l.set(i, l.set(j, l.get(i))); 

Es ist nur ein Element aus einem Index zum anderen setzen.

Für Thread-Safe: müssen Sie Listen Thread sicher machen nicht die Swap-Methode, verwenden Sie unten Code, um Ihre Liste Thread sicher. Und dann Liste verwenden.

Collections.synchronizedList(yourList). 
+0

so wird es dann kein problem sein? Ich sehe hier keine gleichzeitigen Probleme. – Zip

+0

siehe die aktualisierte Antwort –

5

Wenn Sie über einen ConcurrentModificationException besorgt sind, ja, Swap-Aufruf von innerhalb der Schleife ist sicher.

Die erweiterte for-Schleife verwendet intern einen Iterator, und ein Iterator kann ConcurrentModificationException auslösen, wenn er eine strukturelle Änderung der Liste erkennt, die nicht vom Iterator selbst ausgeführt wird. Obwohl Sie die Liste ändern, tun Sie nicht eine strukturelle Änderung: eine strukturelle Änderung ist eine Änderung, in der die Größe der Liste (oder der Sicherungsarray) ändert. Lediglich das Setzen eines Wertes gilt nicht als strukturelle Änderung. Vom Java API documentation:

(eine strukturelle Modifikation ist jede Operation, die oder löscht ein oder mehrere Elemente hinzufügt oder ändert die Größe explizit die Trägermatrix; lediglich den Wert eines Elements Einstellung ist keine strukturelle Änderung.)

Allerdings ist die Verwendung der indexbasierten for-Schleife in Ihrem Fall schneller. Der Grund ist, dass der Aufruf indexOf(temp) tatsächlich das Objekt finden muss, um seinen Index zu erhalten, sodass er die Listenelemente erneut durchlaufen muss. Ihr Algorithmus hat also eine quadratische Laufzeit. In der indexbasierten for-Schleife kennen Sie bereits den Index des Elements, das Sie tauschen möchten, daher ist dies nicht notwendig und Sie haben eine lineare Laufzeit.

1

Ich denke, Ihre Frage ist 'Möge dies eine ConcurrentModificationException werfen?'

die Frage zu beantworten, sollten Sie wissen, wann und warum ein ConcurrentModificationException in einer Sammlung geworfen werden.
Nehmen ArrayList zum Beispiel:

  • ArrayList hat ein Feld modCount die modification count bedeutet. Wenn einige Methoden aufgerufen werden, die strukturelle Änderung zu verursachen, wie add()/remove(), wird die modCount``(modCount++) erhöhen.
  • ArrayList.Iterator hat ein Feld expectedModCount, das von der ArrayList modCount zugewiesen wird, wenn erstellt. Wenn next() oder remove() aufgerufen wird, wird die expectedModCount mit modCount verglichen, wenn nicht gleich wird eine ConcurrentModificationException geworfen werden.
  • Collections.swap ‚s-Quellcode:

    public static void swap(List<?> list, int i, int j) { 
        final List l = list; 
        l.set(i, l.set(j, l.get(i))); 
    } 
    

    Collections.swap ruft set() Methode der Arraylist, die nicht die modCount nicht erhöht, so wird es die ConcurrentModificationException nicht verursachen.

Verwandte Themen