Java doc says that return values of method values() and entrySet() are backed by the map. So changes to the map are reflected in the set and vice versa. I don't want this to happen to my static copy. Essentially, I want lots of concurrent operations to be done on my DS. But for some cases I want to iterate over its static snapshot. I want to iterate over static snapshot, as I am assuming iterating over static snapshot will be faster as compared to a version which is being updated concurrently.
-
1Do you intend to iterate over a single static snapshot many times, or is your plan basically `for (final Map.Entry<..., ...> entry : takeStaticSnapshot(map)) { doStuff(); }`? (I ask because in the latter case, I don't think there's any way to take a static snapshot without implicitly iterating over the map anyway. And in *either* case, you should be aware that such a snapshot would not be atomic.) – ruakh Jun 13 '16 at 05:35
-
Define "snapshot". Will any copy do, or does it have to be consistent/atomic/point-in-time ? – Thilo Jun 13 '16 at 05:40
-
1" I am assuming iterating over static snapshot will be faster as compared to a version which is being updated concurrently." I would profile that before jumping to conclusions / effort of snapshotting. – Thilo Jun 13 '16 at 05:44
-
http://stackoverflow.com/a/32141829/14955: "the performance for ConcurrentHashMap is slightly worse when you need to use it from more than one thread but it is not a critical aspect of performance that you should be worried about." – Thilo Jun 13 '16 at 05:45
-
@Thilo Thanks. What about performance of ConcurrentLinkedQueue? Is it as good or as bad as ConcurrentHashMap or Con.HashMap is faster? And yes any snapshot will do? I just need that to be approximate. – PHcoDer Jun 13 '16 at 05:54
-
@ruakh I intend to iterate multiple times. 3-4 times. – PHcoDer Jun 13 '16 at 06:03
-
Unless you are want to be sure that it doesn't change between iterations or profiling shows significant performance problems, I wouldn't bother with it. – Sergei Tachenov Jun 13 '16 at 06:07
-
@SergeyTachenov How about Concurrent Linked Queue? In my program, the bottleneck function is using ConcurrentLinkedQueue. I am thinking to replace it with ConcurrentHashMap and then use a static snapshot of this CHM in the bottleneck method. So actually I will be transitioning from Con.LinkedQ to CHM also. How is the performance of CLQ as compared to CHM. Any idea? – PHcoDer Jun 13 '16 at 06:16
-
You should measure the performance in your particular case. As far as I know, linked queues have pretty good degree of concurrency due to the lack of common memory (as opposed to array queues). But then again, CHM has pretty good performance too. Only measurement can tell. – Sergei Tachenov Jun 13 '16 at 14:19
2 Answers
Just make a copy, and it wont be changed.
Set<K> keySetCopy = new HashSet<>(map.keySet());
List<V> valuesCopy = new ArrayList<>(map.values());
All collection implementations have a copy constructor which will copy the entire data of the supplied collection to the newly created one, without being backed by the original.
Note: this won't work with entrySet()
, as the actual Map Entries will still "belong" to the original Map and changes to the original entries will be reflected in your copies. In case you need the entrySet()
, you should copy the entire Map first, with the same technique.
Set<Entry<K,V>> entrySetCopy = new HashMap<>(map).entrySet();
Note that all of these will require a full iteration ONCE (in the constructor) and will only then be static snapshots. There is no way around this limitation, to my knowledge.

- 292,901
- 67
- 465
- 588
-
3Note that this still involves iterating over the original ConcurrentHashMap, so it may not satisfy the OP's requirements. – ruakh Jun 13 '16 at 05:39
-
@SeanPatrickFlyod Thanks. I had another doubt. Say, I have a ConcurrentHashMap CHM whose values are object of Class A. So values in CHM will be pointers of objects of type A call one of them as p. So if I make a copy of CHM.values() in an ArrayList AL. AL will contain p. Now if I make a change to a property of object p refer to. That will be reflected when I access it later from CHM. Right? – PHcoDer Jun 13 '16 at 05:40
-
1Yes, the contained objects are shared, so changes will be visible in both original map and snapshot (modulo cross-thread propagation). – Thilo Jun 13 '16 at 05:42
-
4I would suggest iterate entrySet(). If you iterate keySet and values, it's possible
doesn't match. Also be careful about NPE(http://apurvagnihotri.blogspot.com/2010/06/concurrenthashmap-be-careful-while.html) – waltersu Jun 13 '16 at 06:06 -
@ruakh those requirements are pretty much impossible, so I offered the next best thing – Sean Patrick Floyd Jun 13 '16 at 06:39
-
@SeanPatrickFloyd: Except that "the next best thing" would be, *not* doing this. And while I'm all for answers that say "that's not possible, but you can ___", it's dishonest to just present the ___ part in its own and imply that it does what the question asks. – ruakh Jun 13 '16 at 15:42
-
@ruakh so, rather than providing a reasonable alternative, you prefer to say "not possible"? Jeez, it must be fun working with you – Sean Patrick Floyd Jun 13 '16 at 15:47
-
@SeanPatrickFloyd: Of *course* it's good to provide alternatives -- which is what I just said. But you have to make clear that that's what you're doing. If someone asks for directions to Main Street, and you only know part of the way, you should give the partial directions; but you shouldn't imply that your partial directions will bring them exactly to Main Street. (Especially if, to strain the analogy, they won't necessarily be able to tell that they're not actually at Main Street.) – ruakh Jun 13 '16 at 16:22
-
-
Don't you need to copy the objects as well? - Otherwise the new collection references the same objects. – Markus Jun 15 '16 at 12:54
-
1@Markus if the objects are mutable, yes. But I'd say that's outside the scope of this question. In fact it may even be the OP's intention to get at the original objects – Sean Patrick Floyd Jun 15 '16 at 14:29
Simply make a copy, new HashMap would be independent of the original one.
Set<K> keySetCopy = new HashSet<>(map.keySet());
List<V> valuesCopy = new ArrayList<>(map.values());
However mind that this will take a full iteration over the concurrentStructure, once but will only then be static snapshots. So you will need time equivalent to one full iteration.

- 546
- 3
- 10