Is there a simple way to get BiMap functionality using a Cache, or will I have to roll my own solution?
There's Maps.synchronizedBiMap
, but I don't think that it's good starting point, as adding all the Cache
capabilities is probably way harder than adding the Bi
to a Cache
.
It's also just synchronized, not concurrent.
Is there a BiMap implementation that allows concurrent access,
AFAIK no.
or will I have to use read-write locks if I want efficient, multi-threaded access?
I guess, it depends of what part of the BiMap
functionality you need. The BiMap
allows you
- to
get
and put
in both directions
- to preserve bijectivity either via
forcePut
or via put
throwing an exception on conflicts
If you're sure that no conflicts may ever happen, then it's not that complicated. Maybe all you need is to piggyback two caches like I did here.
AFAIK for preserving bijectivity, you'd need locks. If writes are not too common, then you're done quickly with a single ReadWriteLock
. Otherwise....
You could try to use Striped
for maximum concurrency, but I'm afraid, it's too tricky as you'd need to lock a stripe depending on both the key and the value. And also on previous value in case of forcePut
.
Whenever I used BiMap
, I found out later either that I actually need to get something in more than two different ways (some secondary key) or that I need to get some additional information. So I converted it to two or three maps in a class like
void put(K1 k1, K2 k2, E extraInfo) {
MyEntry<K1, K2, E> e = new MyEntry<>(k1, k2, extraInfo);
firstMap.put(k1, e);
secondMap.put(k2, e);
}
MyEntry<K1, K2, E> getByFirstKey(K1 k1);
MyEntry<K1, K2, E> getBySecondKey(K2 k2);
It's a bit hacky, but simple and maybe it applies to your cache as well.