Friday, April 19, 2024
HomeJavaThe way to use Map.compute(), computeIfPresent() and ComputeIfAbsent in Java? HashMap and...

The way to use Map.compute(), computeIfPresent() and ComputeIfAbsent in Java? HashMap and ConcurrentHashMap Instance


The JDK 8 has added a number of helpful strategies in current interfaces e.g. java.util.Map, java.util.Assortment, and java.util.concurrent.ConcurrentMap. Because of default strategies, the much-needed evolution of current interfaces turns into potential. Out of many helpful strategies, one methodology which stands out to me is the compute() methodology, which lets you replace a price in ConcurrentHashMap atomically. As per Java documentation, The compute() perform tries to compute a mapping for the required key and its present mapped worth (or null if there is no such thing as a present mapping). The whole perform is carried out atomically.

Some tried replace operations on this map by different threads could also be blocked whereas the computation is in progress, so the computation needs to be quick and easy, and should not try and replace every other mappings of this Map. In easy phrases, you should utilize this methodology to atomically replace a price for a given key within the ConcurrentHashMap.

You need to use the compute() methodology to replace an current worth inside ConcurrenHashMap. For instance, to both create or append a String msg to a price mapping:

map.compute(key, (okay, v) -> (v == null) ? msg : v.concat(msg))

If the perform returns null, the mapping is eliminated (or stays absent if initially absent).

If the perform itself throws an (unchecked) exception, the exception is rethrown, and the present mapping is left unchanged

There are additionally variants of compute() methodology like computeIfPresent() and computeIfAbsent(), which computes the brand new worth provided that an current worth is current or absent.

For instance, you may replace a map of LongAdder utilizing computeIfAbsent as proven beneath:

map.computeIfAbsent(key, okay -> new LongAdder()).increment();

Right here the constructor of LongAdder class will solely be known as when a brand new counter is definitely wanted. If a price exists then it’s returned from ConcurrentHashMap, much like the putIfAbsent() methodology.  You possibly can additional see The Full Java MasterClass course on Udemy by Tim Buchalaka and his workforce to be taught extra about new strategies added to the present API in Java 8.

Now, let’s examine the code in motion:

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.LongAdder;

/*
 * Java Program to make use of compute() methodology of Java 8
 * to atomically replace values in ConcurrentHashMap
 */
public class Howdy {

  public static void foremost(String[] args) throws Exception {

    // a ConcurrentHashMAp of string keys and Lengthy values
    ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();
    map.put("apple", 3);
    map.put("mango", 4);
    
    System.out.println("map earlier than calling compute: " + map);

    // in JDK 8 - you may also use compute() and lambda expression to
    // atomically replace a price or mapping in ConcurrentHashMap
    map.compute("apple", (key, worth) -> worth == null ? 1 : worth + 1);
    
    System.out.println("map after calling compute on apple: " + map);

    // you may also use computeIfAbsent() or computeIfPresent() methodology
    // Constructor of LongAdder might be solely known as when a price for
    // given key just isn't exists
    ConcurrentMap<String, LongAdder> map2 = new ConcurrentHashMap<>();
       
    System.out.println("map with LongAdder earlier than calling compute: " + map2);
    
    map2.computeIfAbsent("apple", key -> new LongAdder()).increment();
    map2.computeIfAbsent("mango", key -> new LongAdder()).increment();
    map2.computeIfAbsent("apple", key -> new LongAdder()).increment();
    
    System.out.println("map with LongAdder after calling compute on 
                            apple, mango, apple: " + map2);

  }
}

Output:
map earlier than calling compute: {apple=3, mango=4}
map after calling compute on apple: {apple=4, mango=4}
map with LongAdder earlier than calling compute: {}
map with LongAdder after calling compute on apple, mango, apple: {apple=2, mango=1}

How does compute() and computeIfPresent works in Java


Now, let’s attempt to perceive what’s occurring right here.

Within the first line, now we have merely created a Concurrent HashMap with two keys apple and mango, and their values are their depend like what number of apples now we have and what number of mangoes now we have.

Now, we bought yet another apple and we have to replace the depend on our bucket, for that, we’re calling the compute() methodology as proven beneath:

map.compute("apple", (key, worth) -> worth == null ? 1 : worth + 1);

That is simply incrementing the worth for this key, therefore the depend of “apple” moved from 3 to 4, which is proven in our second print assertion.

Within the second instance, now we have an empty ConcurrentHashMap and our job is so as to add keys and their counts in real-time. That is suited to situations like you might be doing a sale and you should maintain monitor of what number of copies of a selected e book or course are offered.

One other helpful situation is studying via a textual content file and printing the depend of every phrase that seems within the file.

Anyway, the important thing level right here is that the map is initially empty which is proven within the third print assertion. After that, now we have added 2 apples and 1 mango to this map utilizing computeIfAbsent() methodology and it has created a LongAdder object for every key and saved that as a price.

The benefit of this methodology is that the LongAdder object is simply created when a secret’s first time added i.e. it was absent initially, after that, the depend is incremented within the LongAdder object.

It is a significantly better approach to improve a counter in a concurrent Java utility, however LongAdder is simply out there from Java 8.

That is why once we printed map2, we see that there are two apples and 1 mango is current in our concurrent map. You possibly can additional see The Final Java 8 Tutorial – From newbie to skilled to be taught extra about LongAdder and a number of other different helpful new courses added in JDK 8 API.

Right here is the screenshot of this program with output:

Java 8 compute() and computeIfPresent() Example

Necessary factors about compute() methodology of Java 8

Now that you realize what’s compute() methodology and what does it do and easy methods to use it in a Java program, it is time to revise among the vital issues about this methodology.

Listed here are a few factors which is price remembering:

1) It permits you to atomically replace a price in ConcurrentHashMap.

2) It has variants like computeIfAbsent() and computeIfPresent() which computes values accordingly.

3) You can even use merge() instead of the compute() for updating an current worth.

That is all about easy methods to use the compute() methodology in Java 8. You need to use this methodology to replace the values of a selected key in ConcurrentHashMap in Java atomically. That is the principle factor, it permits atomic insert and replace with none specific synchronization. 

You can even use it to insert depend for brand spanking new keys. It is notably helpful for populating a concurrent hash map with keys and their counts e.g. studying a textual content file and print counts of all phrases. 

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments