In Java, I often need to lazily get an entry of a ConcurrentMap, creating only if necessary.
For example I may have
ConcurrentMap<String, AtomicReference<Something>> a = new ConcurrentHashMap<>();
ConcurrentMap<String, Something> b = new ConcurrentHashMap<>();
I wanted to make a generic function to do this job so that I don't repeat myself the rather cumbersome double checking code for every type.
the following was as far as I can get:
<K, V, C extends V> V ensureEntry(ConcurrentMap<K, V> map, K key, Class<? super C> clazz) throws Exception {
V result = map.get(key);
if (result == null) {
final V value = (V)clazz.newInstance();
result = map.putIfAbsent(key, value);
if (result == null) {
result = value;
}
}
return result;
}
And then I can use it like:
AtomicReference<Something> ref = ensureElement(a, "key", AtomicReference.class);
Something something = ensureElement(b, "another key", Something.class);
The question is that: the function is quite dirty and still has an unsafe generic class cast (the (V)). Would a completely generic and cleaner one possible? maybe in Scala?
Thanks!
With Java 8 lambda, the following is the simplest I could get..
<K, V> V ensureEntry(ConcurrentMap<K, V> map, K key, Supplier<V> factory) {
V result = map.get(key);
if (result == null) {
V value = factory.get();
result = map.putIfAbsent(key, value);
if (result == null) {
result = value;
}
}
return result;
}
ConcurrentMap<String, AtomicReference<Object>> map = new ConcurrentHashMap<>();
ensureEntry(map, "key", () -> new AtomicReference<>());
// or
ensureEntry(map, "key", AtomicReference::new);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With