2016-01-25 2 views
5

Gibt es für einen bestimmten Typ von Map irgendwelche Garantien dafür, dass das Iterieren über die Collection-Ansichten, die von den Methoden keySet, values und entries zurückgegeben werden, in derselben Reihenfolge wiederholt wird?Ist die Iterationsreihenfolge über die verschiedenen Collection-Ansichten einer bestimmten Map hinweg konsistent?

Hintergrund: Ich frage mich, ob

Transformieren
public static void doSomethingForEachEntry(Map<String, Integer> someMap) { 

    for (String key : someMap.keySet()) { 
     doSomething(someMap.get(key)); 
    }  
} 

zu

public static void doSomethingForEachEntry(Map<String, Integer> someMap) { 

    for (Integer value : someMap.values()) { 
     doSomething(value); 
    }  
} 

garantiert Iterationsreihenfolge unverändert zu halten.

+0

Es scheint, die Frage im Titel und in Ihrem Beitrag ist nicht das Gleiche. Was willst du genau wissen? Wenn die Reihenfolge der Schlüssel zurückgibt, ist das gleiche wie die Reihenfolge der Werte?Oder wenn die Bestellung beim zweiten Anruf dieselbe ist wie beim ersten Anruf? – Tunaki

+1

Sie sollten sich nicht auf die Reihenfolge der Iteration verlassen (es sei denn, Sie verwenden eine geordnete Map, z. B. TreeMap). Wenn Sie z. B. eine HashMap verwenden, geben sowohl "values ​​()" als auch "keySet()" für den aktuellen Status der Map die gleiche Iterationsreihenfolge an. Nach dem Hinzufügen von Elementen zur HashMap kann sich die Reihenfolge ändern. – Eran

+0

@Tunaki Meine Frage ist, ob die Reihenfolge der Schlüssel die gleiche wie die Reihenfolge der Werte in dem Sinne ist, dass beide Code-Snippets Werte in der gleichen Reihenfolge verarbeiten würden. – Hulk

Antwort

7

Es ist zwar richtig, dass Sie nicht auf eine bestimmte Bestellung verlassen können, es sei denn die Map Implementierung explizit definiert, gibt es einen Satz in the API documentation, die es bedeutet, ist eine einzige gemeinsame Ordnung für die Karte und alle seine Sammlung Ansichten:

die Reihenfolge einer Karte ist wie die Reihenfolge festgelegt, in dem die Iteratoren auf der Sammlung Ansichten der Karte ihre Elemente zurück.

(Hervorhebung von mir)

Für diese zufrieden zu sein, eine Karte eine inhärente Ordnung hat (auch wenn es nicht angegeben werden kann, und kann sich ändern, wenn die Karte geändert wird) und alle Sammlung Ansichten müssen entsprechen dieser Reihenfolge. Ob dies eine Garantie darstellt und insbesondere, ob alle Kartenimplementierungen von Drittanbietern dies gewährleisten, ist eine andere Frage.

Es ist auch erwähnenswert, dass diese in der Map Schnittstelle als Ansichten explizit definiert, die von der Karte unterstützt werden, (zB wenn Sie ein Element aus den keySet entfernen, wird die entsprechende Map Eintrag muss von der entfernt werden Karte). Dies bedeutet in der Realität, dass es weniger wahrscheinlich ist, dass Sie von einer korrekten Map-Implementierung andere Ordnungen erhalten, als wenn Sie beispielsweise flache Kopien der Sammlungsansichten erstellt hätten.

Nachdem all das gesagt wurde, wenn die Frage lautet: "Ist das ein sicherer Refactor?" dann lautet die Antwort "ja, solange der ursprüngliche Code nicht selbst gebrochen ist". Wenn die Methode auf einer bestimmten Reihenfolge und daher einer bestimmten Map Implementierung basiert, sollte die Methode so deklariert werden, dass nur dieser Typ von Map akzeptiert wird. Andernfalls haben Sie eine potentielle Zeitbombe, wenn die zugrundeliegende Map Implementierung die Linie nach unten ändert (und ich habe gesehen, dass Software im wirklichen Leben deswegen mit einem JDK-Update bricht).

Wenn ein bestimmten Anrufer auf einer bestimmte Reihenfolge unter Berufung, weil sie es vorbei eine geordnete Map Implementierung wissen, das ist in Ordnung und die Bestellung wird nach dem Refactoring erhalten bleiben.

+1

Gute Punkte. Und ich habe noch kein Gegenbeispiel gefunden. Ich habe Tests für alle in meiner Codebase verwendeten "Map" -Typen hinzugefügt, aber es wäre gut zu wissen, ob diese Transformation (die von statischen Analysewerkzeugen vorgeschlagen wird und wahrscheinlich sowohl die Lesbarkeit als auch die Leistung erhöht) garantiert sicher ist. – Hulk

+0

@Hulk hat ein paar Gedanken über die "garantiert sicher sein" -Frage hinzugefügt - nichts, was Sie nicht bereits wissen, aber es lohnt sich, es trotzdem zu sagen – CupawnTae

+0

Nach etwas mehr Forschung, stimme ich zu. Für [SortedMaps] (https://docs.oracle.com/javase/8/docs/api/java/util/SortedMap.html) gibt es die zusätzliche Garantie * Eine Karte, die zusätzlich eine Gesamtordnung für ihre Schlüssel bereitstellt. Die Map wird nach der natürlichen Reihenfolge ihrer Schlüssel oder nach einem Comparator angeordnet, der normalerweise zum Zeitpunkt der sortierten Kartenerstellung bereitgestellt wird. ** Diese Reihenfolge wird bei der Iteration über die Sammlungsansichten der sortierten Map (zurückgegeben von den Methoden entrySet, keySet und values) ** angezeigt. Mehrere zusätzliche Operationen werden bereitgestellt, um die Reihenfolge zu nutzen. * – Hulk

0

Die Iterationsreihenfolge hängt von der spezifischen Implementierung der Map ab, die Sie verwenden. Lesen Sie in der Dokumentation nach, wenn Sie den Kartentyp kennen. Wenn Sie sich nicht darauf verlassen, verlassen Sie sich nicht auf eine Iterationsreihenfolge.