views:

564

answers:

2

Quick background I have a concurrent map I used to cache some values that change quite often (still worth caching them from testing). I want to evict items from my cache at regular intervals by examining an expire time in the value. I am using the keySet() method to get a reference to all my keys and then check the values and if expired i remove them. In other threads the cache is being queried and updated(removed) constantly.

From the javadocs for keySet() it mentioned if the map changes while I am iterating over the keyset Set the results are undefined. Obviously I would like a defined way of dealing with this so the results are valid. Would it be enough to pass the Set to a HashSet and then iterate over this set as it is my understanding this set will not be backed by the map, is this a wasteful of memory way of doing it? Any ideas appreciated.

Unfortunately my evictor is not the only way for items to be removed from the concurrent map so am I correct in saying that I need to copy the keySet to another Set before iterating through it.

Thanks in advance

EDIT: It turns out I was reading the javadocs for the Map keySet() method instead of the ConcurrentMap keySet(). Thanks my bad :)

Returns a set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation), the results of the iteration are undefined. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll retainAll, and clear operations. It does not support the add or addAll operations.

A: 

If an LRU cache will fit the bill well enough for you, check out LinkedHashMap—it makes implementing an LRU cache trivial, and then you can make the results threadsafe by wrapping it with a call to Collections.synchronizedMap.

Hank Gay
+5  A: 

Are you using the Java Concurrent HashMap ? From the keySet() documentation it appears to behave in a fashion which you'd find useful.

Returns a set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. The set supports element removal, which removes the corresponding mapping from this map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations. The view's returned iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

i.e. you can remove stuff and you should be fine.

If you're not using this implementation, then which are you using (and why ? Not being funny, but it would be interesting to know why you've made that choice)

Brian Agnew
Great Thanks Brian ye i am using a concurrent hashmap but when looking at the javadocs was reading the docs for map :) Thanks a million
Paul Whelan