Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent of ComputeIfAbsent in Java 7

Tags:

java

android

Is there a way to run a piece of code only if the key doesn't exist in a ConcurrentHashMap, and save the code's result to the collection?

I can't use Java 8 features because I'm developing for Android.

Also, I would like to avoid running long operations if I don't have to and I don't want to break the collection's atomic operation to do so.

like image 408
shlatchz Avatar asked Nov 15 '16 16:11

shlatchz


People also ask

How to use computeIfAbsent in Java?

computeIfAbsent() Parameters The computeIfAbsent() method takes 2 parameters: key - key with which the computed value is to be associated. remappingFunction - function that computes the new value for the specified key.

What is the difference between putIfAbsent and computeIfAbsent?

computeIfAbsent takes a mapping function, that is called to obtain the value if the key is missing. putIfAbsent takes the value directly. If the value is expensive to obtain, then putIfAbsent wastes that if the key already exists.

Is computeIfAbsent Atomic?

It's important to notice that with computeIfAbsent(), a compound operation is not necessarily atomic because updates are performed outside of the method.

How do I return a map in Java?

HashMap get() Method in Java get() method of HashMap class is used to retrieve or fetch the value mapped by a particular key mentioned in the parameter. It returns NULL when the map contains no such mapping for the key.

What is the use of computeIfAbsent in Java?

HashMap computeIfAbsent() method in Java with Examples. The computeIfAbsent(Key, Function) method of HashMap class is used to compute value for a given key using the given mapping function, if key is not already associated with a value (or is mapped to null) and enter that computed value in Hashmap else null.

How to use computeIfAbsent () method in HashMap in Java?

HashMap computeIfAbsent () method in Java with Examples. Last Updated : 24 May, 2019. The computeIfAbsent (Key, Function) method of HashMap class is used to compute value for a given key using the given mapping function, if key is not already associated with a value (or is mapped to null) and enter that computed value in Hashmap else null.

What is the difference between Java 7 and Java 8 computeIfAbsent?

This is shown to see that there is no difference in the way entries (key-value pairs) are removed from the multi-value map when using the Java 7 way as compared to the Java 8 computeIfAbsent () way.

What is the difference between compute () and computeIfPresent () in Java?

The compute () is a bit similar to computeIfPresent () except that when the key isn’t existent in the map, calling the compute () will raise an exception if you reference the val parameter (the current value for the key in the Map). The second compute () will throw: Exception in thread “main” java.lang.NullPointerException.


1 Answers

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.

like image 191
BeeOnRope Avatar answered Oct 13 '22 23:10

BeeOnRope