2016-06-13 20 views
4

Java doc besagt, dass Rückgabewerte von method values ​​() und entrySet() von der Map unterstützt werden. So werden Änderungen an der Karte in der Menge widergespiegelt und umgekehrt. Ich möchte nicht, dass das mit meiner statischen Kopie geschieht. Im Wesentlichen möchte ich viele gleichzeitige Operationen auf meinem DS durchgeführt werden. Aber in einigen Fällen möchte ich über seinen statischen Snapshot iterieren. Ich möchte über statische Snapshots iterieren, da ich davon ausgehe, dass das Iterieren über statische Snapshots im Vergleich zu einer Version, die gleichzeitig aktualisiert wird, schneller ist.Java: Wie man statischen Schnappschuss von ConcurrentHashMap nimmt?

+1

Haben Sie vor, mehrmals über einen einzelnen statischen Snapshot zu iterieren, oder ist Ihr Plan im Grunde 'für (final Map.Entry <..., ...> entry: takeStaticSnapshot (map)) {doStuff(); } '? (Ich frage, denn im letzteren Fall glaube ich nicht, dass es eine Möglichkeit gibt, einen statischen Snapshot zu erstellen, ohne implizit über die Map zu iterieren. Und in jedem Fall sollten Sie sich darüber im Klaren sein, dass ein solcher Snapshot nicht atomar ist.) – ruakh

+0

Definieren Sie "Snapshot". Wird eine Kopie dies tun, oder muss sie konsistent/atomar/Zeitpunkt sein? – Thilo

+1

"Ich gehe davon aus, dass das Iterieren über statischen Snapshot im Vergleich zu einer Version, die gleichzeitig aktualisiert wird, schneller ist." Ich würde das Profil erstellen, bevor ich voreilige Schlüsse ziehe. – Thilo

Antwort

1

Einfach eine Kopie erstellen, neue HashMap wäre unabhängig von der ursprünglichen.

Beachten Sie jedoch, dass dies eine vollständige Iteration über die ConcurrentStructure dauert, aber nur dann statische Snapshots. Sie werden also Zeit benötigen, die einer vollständigen Iteration entspricht.

7

Erstellen Sie einfach eine Kopie, und es wird nicht geändert.

Set<K> keySetCopy = new HashSet<>(map.keySet()); 
List<V> valuesCopy = new ArrayList<>(map.values()); 

All Sammlung Implementierungen hat eine Kopie Konstruktor, der die gesamten Daten der mitgelieferten Sammlung an den neu erstellte Kopie wird, ohne durch die ursprüngliche gesichert werden.

Hinweis: Dies funktioniert nicht mit entrySet(), da die tatsächlichen Karteneinträge immer noch zur ursprünglichen Karte "gehören" und Änderungen an den ursprünglichen Einträgen in Ihren Kopien wiedergegeben werden. Falls Sie die entrySet() benötigen, sollten Sie zuerst die gesamte Map mit derselben Technik kopieren.

Set<Entry<K,V>> entrySetCopy = new HashMap<>(map).entrySet(); 

Beachten Sie, dass alle diese wird einmal voll Iteration erfordern (im Konstruktor) und wird nur dann statische Schnappschüsse sein. Um diese Einschränkung herum gibt es meines Wissens keine Möglichkeit.

+2

Beachten Sie, dass hierbei immer noch die ursprüngliche ConcurrentHashMap durchlaufen wird, sodass die Anforderungen des OP möglicherweise nicht erfüllt werden. – ruakh

+0

@SeanPatrickFlyod Danke. Ich hatte noch einen Zweifel. Angenommen, ich habe ein ConcurrentHashMap-CHM, dessen Werte Objekte der Klasse A sind. Also sind die Werte in CHM Zeiger von Objekten des Typs A. Rufen Sie eines davon als p auf. Also wenn ich eine Kopie von CHM.values ​​() in einer ArrayList AL mache. AL enthält p. Nun, wenn ich eine Änderung an einer Eigenschaft des Objekts p beziehe. Das wird widergespiegelt, wenn ich später von CHM darauf zugreife. Recht? – PHcoDer

+1

Ja, die enthaltenen Objekte werden gemeinsam verwendet, sodass Änderungen sowohl in der Originalzuordnung als auch in der Momentaufnahme sichtbar sind (Modulo-Cross-Thread-Propagierung). – Thilo