Equivalent of ComputeIfAbsent in Java 7

There is no exact equivalent, but the usual approach is something like this:

ConcurrentMap<Key,Value> map = ...

Value computeIfAbsent(Key k) {
  Value v = map.get(k);
  if (v == null) {
    Value vNew = new Value(...); // or whatever else you do to compute the value
    v = (v = map.putIfAbsent(k, vNew)) == null ? vNew : v;
  }
  return v;
}

This is pretty much functionally equivalent the computeIfAbsent call in Java 8, with the only difference being that sometimes you construct a Value object that never makes it into the map - because another thread put it in first. It never results in returning the wrong object or anything like that - the function consistently returns the right Value no matter what, but if the construction of Value has side-effects*, this may not be acceptable.

The extra instances are generally not a performance problem because the initial get() check eliminates most of the calls to putIfAbsent. In general this approach can be considerably faster than computeIfAbsent because that call does unnecessary locking of objects when the object already exists. Locally I measured it as 5 times faster if there are some objects that are heavily contended.

If you really need the computing behavior integrated into the map (with an internal lock held so exactly one thread creates the new object), you can use Guava's CacheBuilder to get a LoadingCache. It's essentially the same behavior as Java 8's CHM, but with a ton of additional configuration options.

Tags:

Java

Android