Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For HashMap, is it more efficient to use compute() or put()

Tags:

java

hashmap

I have tried looking around for a while but I can't find a concrete answer and still am having some trouble understanding exactly what the compute method for HashMap does.

The way I understand it at the moment is that compute will allow you to manipulate the value but not set it to a new value (like where the garbage collector will have to get rid of the old object) while put will just get rid of the old object and set it (like going x = new Something).

If my understanding of this is wrong, please tell me, but regardless, is the compute method more efficient in general? Should I use this over put whenever possible or is it only used in certain situations?

like image 473
ReBuff Avatar asked Sep 20 '25 22:09

ReBuff


2 Answers

Use put if you want to set a new value unconditionally. Use compute if you want to compute a new value based on the existing value in the map. You have the option of either changing it to a new value or removing it from the map.

The documentation for compute states that:

The default implementation is equivalent to performing the following steps for this map:

V oldValue = map.get(key);
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != null) {
    map.put(key, newValue);
} else if (oldValue != null || map.containsKey(key)) {
    map.remove(key);
}
return newValue;

It's more complicated than a simple put:

  1. It calls get to retrieve the current value.
  2. It calls the supplied remapping function to convert it to a new value.
  3. It either calls put to overwrite the old value or remove to remove it depending on whether the new value is null or not.

Since ultimately it ends up calling put, compute has more steps and is slower. If put meets your needs—you don't care what's in the map, you just want to set a key to a value—use put.

like image 108
John Kugelman Avatar answered Sep 22 '25 13:09

John Kugelman


TL;DR

Yes, it is more efficient to use compute, instead of get() and put().

Longer version

By using a combination of compute, computeIfPresent computeIfAbsent etc, you can do EXACTLY the same things using compute method as you can do with get and put. (In fact prior to JDK 8, there was no compute and lambda, but we were all able to "get by" without any large gaping holes in our coding lives, although admittedly, the things got better with lambda.)

But the main advantages of using compute method is:

  1. It is more readable (depends on who is doing the reading, of course)
  2. It is atomic - between get and put, things could have changed if you write get and put yourself.
  3. It can be and is generally more efficient. This is evident from the fact that if you see the source code of HashMap.compute method, you will see that it calls the hash function only once. The get and put will call hash function once each, since the underlying data structure knows of those calls as separate calls. In compute, it knows that the put call is "coming", so it can save the hash. Similarly in other implementations, once the key has been "located", it will be reused, rather than being looked up again. The main algorithmic cost of this operation is in the lookup, so doing it once is better than doing it twice.

So, between 2 and 3, there are good reasons to use compute.

like image 44
Amrinder Arora Avatar answered Sep 22 '25 13:09

Amrinder Arora