Reputation: 894
I'm using ConcurrentHashMap
from google guava (via MapMaker), but that implementation isn't ordered.
There is ConcurrentSkipListMap
in google guava, but that structure can't expire.
Is there any structure that can do both?
Upvotes: 4
Views: 3903
Reputation: 4869
It sounds like you want an ordered view of the concurrent expiring map. You could build one from ForwardingMap
Upvotes: 0
Reputation: 310980
Extend java.util.LinkedHashMap and override removeEldestEntry() to do whatever you want it to do.
Upvotes: 1
Reputation: 833
Why not just use two ordered maps? One is keyed by timestamp and is used to find expired events. The other is keyed by UUID and is used to find events. When removing expired events, use the UUID of the event to remove from the second map.
Upvotes: 0
Reputation: 26882
I'd use ConcurrentSkipListMap
and iterate the map periodically to purge expired stuff. Since the skiplist is unbounded this opens up a possibility of a memoryleak, when the eviction thread cannot catch up, but in practice this seems very, very unlikely unless you do something extreme.I've also done something like this when I didn't want to use a background thread:
static AtomicInteger cnt = new AtomicInteger();
Val put(K key, V val){
//Do the usual stuff
if(cnt.getAndIncrement() % 100 == 0){
//iterate map and evict stuff
}
}
The if(cnt.getAndIncrement() % 100 == 0)
may have been a "clever optimization", so perhaps you could just iterate and evict everytime like matt b suggests.
Oh just one caveat when you do this.... Be sure to break equality between different entities when the timestamps coincide:
class Entity implaments Comparable<Entity>{
static AtomicInteger SEQ = new AtomicInteger();
int id = SEQ.getAndIncrement();
long timeStamp = System.currentTimeMillis();
int compareTo(Entity other){
// compare by timestamp
// If timestamps are equal, don't just return 0 yet!!
// Compare by id and return 0 ONLY IF the id equals.
// Otherwise entities disappear from your ordered map and
// it's really annoying to debug.
}
Upvotes: 2
Reputation: 139971
If you have an ordered Map (I'm assuming the ordering is based on timestamp), then whenever you add or get items from the Map, you can simply scan from the least ordered value in the Map to the current timestamp - 60 seconds and remove any that fall short. The ordered property of the Map means you don't need to scan the full list on every operation.
Upvotes: 0
Reputation: 11940
Sounds like you have very specific and unusual requirements. You'll probably have to write it yourself.
Upvotes: 0