Thursday, March 28, 2024
HomeJavaThe best way to replace worth in ConcurrentHashMap atomically in Java? Compute...

The best way to replace worth in ConcurrentHashMap atomically in Java? Compute and ComputeIfAbsent Instance


Good day guys, if in case you have been doing Java improvement then you realize that Java 8 brings quite a lot of adjustments not simply on programming language half by introducing Lambda expression, default strategies on interface, static methodology on interface but in addition on API  and SDK half like Stream API and new Date and Time API. However whereas these larger adjustments get lot of protection many small adjustments however very helpful in each day programming process does not get sufficient point out and plenty of Java programmers are unaware of these. One in every of such enhancement was addition of compute(), computeIfAbsent(), and computeIfPresent() methodology in java.util.Map interface. Including  a brand new methodology on an present interface was not attainable earlier than Java 8 however new function like default and static methodology on interface made it attainable and Java designers take full benefit of those two function to reinforce and enhance present interface like Assortment and Map. 

As a part of that enhancement, computeIfAbsent, compute and computeIfPresent strategies have been added in Java 8 to enhance the performance and value of the java.util.Map interface. These three strategies now gives a handy and environment friendly method to replace values in a map based mostly on some computation, and to make it simpler to implement numerous purposeful programming patterns. 

The perfect factor about this methodology is that they replace worth atomically. 

Earlier than Java 8 and the introduction of those strategies, updating values in a map usually required utilizing get to retrieve the present worth, performing some computation on the worth, after which utilizing put to retailer the consequence again within the ma as proven beneath:

Integer  depend = studentVsBookMap.get(scholar);

if (depend != null){
   
} else {
   
}

The brand new strategies present a extra concise and readable method to carry out these operations, and in addition permit for extra versatile and environment friendly computation. 

On this article, I’ll present you the way you should utilize compute and computeIfAbsent() methodology to simply replace worth in any Map like HashMap and ConcurrentHashMap, however earlier than that allow’s discover out what’s compute() and computeIfAbsent() methodology do and how one can use them with examples:

The best way to use compute() methodology of ConcurrentHashMap in Java

As I mentioned compute() methodology in Java is a technique of the java.util.Map interface and that is why its obtainable to all the category which implements Map interface like HashMap, LinkedHashMap, TreeMap and ConcurrentHashMap. 

It takes a key as an argument and modifies the worth related to that key utilizing a offered operate. The tactic returns the earlier worth related to the important thing, or null if the important thing was not current within the map.

The tactic signature for compute is as follows:

V compute(Ok key, BiFunction<Ok, V, V> remappingFunction)

the place Ok is the kind of the important thing, V is the kind of the worth, and BiFunction<Ok, V, V> is a java.util.operate.BiFunction that takes a key and its related worth, and returns a brand new worth to interchange the outdated one.

Here is an instance that demonstrates using the compute methodology:

import java.util.HashMap;
import java.util.Map;
import java.util.operate.BiFunction;

public class Essential {
  public static void major(String[] args) {
    Map<String, Integer> map = new HashMap<>();
    map.put("A", 1);
    map.put("B", 2);

    BiFunction<String, Integer, Integer> remappingFunction 
     = (key, worth) -> worth + 1;

    Integer oldValue = map.compute("A", remappingFunction);
    System.out.println("Outdated worth of A: " + oldValue); 
    System.out.println("New worth of A: " + map.get("A")); 

    oldValue = map.compute("C", remappingFunction);
    System.out.println("Outdated worth of C: " + oldValue); 
    System.out.println("New worth of C: " + map.get("C")); 
  }
}

On this instance, the compute methodology is used to replace the worth related to a key within the map. If the important thing exists, its worth is up to date utilizing the offered remappingFunction. If the important thing doesn’t exist, the strategy inserts the important thing with its computed worth. You may see there is no such thing as a if-else logic or no null examine required as we have now to do in first instance with out utilizing compute() operate.

How to update value in ConcurrentHashMap atomically in Java

What’s computeIfAbsent() methodology in Java?

Now that you’re aware of the compute() methodology, let’s have a look at its two cousins or variants, computeIfAbsent() and computeIfPresent()

The computeIfAbsent methodology takes a key as an argument and returns the worth related to that key if it exists, or computes and inserts the worth related to the important thing utilizing a offered operate if it doesn’t. 

The tactic returns the worth related to the important thing, both from the map or the results of computing it.

The tactic signature for computeIfAbsent is as follows:

V computeIfAbsent(Ok key, Perform<Ok, V> mappingFunction)

the place Ok is the kind of the important thing and V is the kind of the worth. The mappingFunction is a java.util.operate.Perform that takes a key and returns a worth to be related to that key.

Here is an instance that demonstrates using computeIfAbsent:

import java.util.HashMap;
import java.util.Map;
import java.util.operate.Perform;

public class ComputeIfAbsentDemo{
  public static void major(String[] args) {
    Map<String, Integer> map = new HashMap<>();

    Perform<String, Integer> mappingFunction = s -> s.size();

    Integer worth = map.computeIfAbsent("Good day", mappingFunction);
    System.out.println(worth); 

    worth = map.computeIfAbsent("World", mappingFunction);
    System.out.println(worth); 
  }
}

On this instance, the computeIfAbsent methodology is used to insert the size of a string as its worth within the map if the important thing doesn’t exist already within the map. If the important thing exists, the strategy returns its related worth with out computing it once more.


ComputeIfAbsent Instance in Java utilizing Factorial and ConcurrentHashMap

Right here is my full Java program to show how one can use computeIfAbsent with an actual world instance of calculating factorial and utilizing ConcurrentHashMap as a cache in Java. 

On this instance, I’ve used ConcurrentHashMap as a cache to retailer beforehand calculated factorial values. It is much like memoization which is utilized in Dynamic Programming, significantly whereas calculating Nth Fibonacci quantity.

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
 
/**
* Java ConcurrentHashMap computeIfAbsent Instance
*/
public class ComputeIfAbsentDemo {
 
    static Map<Integer, Lengthy> cache = new ConcurrentHashMap<>();
 
    public static void major(String[] args) throws Exception {
 
        System.out.println("Factorial with out Memoization in Java");
        factorial(6);
 
        System.out.println("Factorial with Memoization in Java -"
                + " Utilizing ConcurrentHashmap computeIfAbsent()");
        factorialInJava8(6);
 
        System.out.println("Calculating factorial second time,
                     with out Memoization");
        factorial(7);
 
        System.out.println("Calculating factorial second time 
               with memoization");
        factorialInJava8(7);
    }
 
    public static lengthy factorial(int num) {
        if (num == 0) {
            return 1;
        }
        System.out.println("Calculating factorial(" + num + ")");
        return num * factorial(num - 1);
    }
 
    public static lengthy factorialWithMemoization(int quantity) {
        if (quantity == 0) {
            return 1;
        }
        Lengthy factorial = cache.get(quantity);
        if (factorial == null) {
            synchronized (cache) {
                factorial = cache.get(quantity);
                if (factorial == null) {
                    System.out.println("Calculating factorial of " 
                             + quantity);
                    factorial = factorial(quantity - 1);
                    cache.putIfAbsent(quantity, factorial);
                }
            }
        }
 
        return factorial;
 
    }
 
    public static lengthy factorialInJava8(int enter) {
        if (enter <= 1) {
            return 1;
        }
        return cache.computeIfAbsent(enter, (quantity) -> {
            System.out.println("Calculating factorial of " + quantity);
            return enter * factorialInJava8(enter - 1);
        });
    }
 
}
Output
run:
Factorial with out Memoization in Java
Calculating factorial(6)
Calculating factorial(5)
Calculating factorial(4)
Calculating factorial(3)
Calculating factorial(2)
Calculating factorial(1)
Factorial with Memoization in Java - Utilizing ConcurrentHashmap computeIfAbsent()
Calculating factorial of 6
Calculating factorial of 5
Calculating factorial of 4
Calculating factorial of 3
Calculating factorial of 2
Calculating factorial second time, with out Memoization
Calculating factorial(7)
Calculating factorial(6)
Calculating factorial(5)
Calculating factorial(4)
Calculating factorial(3)
Calculating factorial(2)
Calculating factorial(1)
Calculating factorial second time with memoization
Calculating factorial of 7
As talked about earlier than, we’re utilizing the newly added Map.computeIfAbsent() methodology to calculate a brand new worth from a supply operate provided that we don’t have already got a worth for a given key. Caching! And since this methodology is assured to execute atomically, and since we’re utilizing a ConcurrentHashMap, this cache is even thread-safe with out resorting to manually making use of synchronized anyplace. And it may be reused for stuff apart from calculating factorial or Fibonacci numbers

Execs and Cons of compute() and computeIfAbsent() methodology

Now that you’ve got understood what’s compute() methodology and its variant like computeIfAbsent or computeIfPresent, its time to see the professionals and cons of utilizing them. Here’s a checklist of benefits and downsides of utilizing computeIfAbsent, compute, and computeIfPresent strategies in Java:

1. Clear and Concise code

These strategies present a extra concise and readable method to replace values in a map based mostly on some computation, in comparison with utilizing get and put strategies.

2. Atomic

These methodology replace values atomically so you do not want exterior synchronization. 

3. Improved efficiency

The strategies are designed to be environment friendly, they usually can typically carry out higher than utilizing get and put strategies, particularly in instances the place the computation is dear or the hot button is not discovered within the map.

4. Improved purposeful programming

These strategies make it simpler to implement purposeful programming patterns and to jot down code that’s extra expressive, maintainable, and reusable.

Thus far we have now seen all benefits however nothing on this world is free as they are saying there is no such thing as a free lunch, so these methodology additionally comes with few challenges. Listed below are frequent cons of utilizing computeIfAbsent, compute, and computeIfPresent strategies in Java:

1. Unfamiliarity

These strategies are comparatively new and never as extensively used because the older get and put strategies, so some builders will not be aware of them.

2. Extra complicated logic

These strategies may be extra complicated to grasp and use appropriately, particularly for builders who usually are not aware of purposeful programming ideas.

3. Efficiency trade-offs

The efficiency advantages of those strategies rely on the precise use case and implementation, and there could also be conditions the place utilizing get and put strategies is extra environment friendly.
That is all about how one can use compute, and computeIfAbsent methodology to replace a worth atomically in a Java Map. The strategies have been launched to supply a extra concise and readable method to carry out these operations, and in addition permit for extra versatile and environment friendly computation. Moreover, these strategies are helpful in conditions the place that you must carry out some operation on a worth within the map, however provided that a key’s current or absent, as they supply a extra concise means to try this.

Whereas they’re nice in some ways are additionally few issues which that you must think about whereas utilizing  computeIfAbsent, compute, and computeIfPresent strategies in Java,  and a very powerful of them is efficiency implications.  As with every software program design resolution, you will need to think about the efficiency implications of utilizing these strategies, and to judge whether or not they’re applicable to your particular use case.

Different Java 8 Tutorial you might like

  • 5 Books to Study Java 8 from Scratch (books)
  • High 5 Programs to study Java 8 Lambda and Stream (programs)
  • The best way to type the map by keys in Java 8? (instance)
  • The best way to use filter() methodology in Java 8 (tutorial)
  • 20 Examples of Date and Time in Java 8 (tutorial)
  • The best way to use Stream class in Java 8 (tutorial)
  • Distinction between summary class and interface in Java 8? (reply)
  • The best way to convert Listing to Map in Java 8 (answer)
  • The best way to use peek() methodology in Java 8 (instance)
  • The best way to format/parse the date with LocalDateTime in Java 8? (tutorial)
  • The best way to type the might by values in Java 8? (instance)
  • The best way to be part of String in Java 8 (instance)
  • 10 examples of Optionals in Java 8? (instance)

Thanks for studying this text to date. Should you like this Java 8 compute and computeIfAbsent tutorial and instance then
please share it with your folks and colleagues. When you have any
questions or ideas then please drop a remark.

P. S. – If you’re new to Java 8 options, significantly lambda
expression and Stream API, and searching for a free on-line course to
enhance your purposeful programming expertise then you may as well be part of Java 8 Purposeful Programming: Lambda Expressions Shortly (FREE) course on Udemy. It is utterly free and greater than 27,000 college students have already benefited from it



RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments