DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Floyd's Cycle Algorithm for Fraud Detection in Java Systems
  • Merge Multiple PDFs in MuleSoft
  • Scaling Java Microservices to Extreme Performance Using NCache
  • What Is a Jagged Array in Java With Examples?

Trending

  • The End of “Good Enough Agile”
  • Creating a Web Project: Caching for Performance Optimization
  • Modern Test Automation With AI (LLM) and Playwright MCP
  • Efficient API Communication With Spring WebClient
  1. DZone
  2. Data Engineering
  3. Data
  4. How to Use Java HashMap Effectively

How to Use Java HashMap Effectively

Struggling with HashMaps? Here's how to effectively use Java HashMaps.

By 
A N M Bazlur Rahman user avatar
A N M Bazlur Rahman
DZone Core CORE ·
Nov. 26, 18 · Tutorial
Likes (67)
Comment
Save
Tweet
Share
168.6K Views

Join the DZone community and get the full member experience.

Join For Free

HashMap is one of the most used data structures that we use in our day-to-day Java programming.

In this article, we are going to explain what, why, and how to use HashMap in Java effectively. Before indulging you into the deep technicalities of theHashMap, let’s first look at an example.

You have a grocery store and there are lots of items in your shop. The names and prices of these products vary. It can be difficult to remember all of these products. While you have written all these products down in a notebook, whenever you sell a product, you have to look at that notebook to find out the price, etc.

If the names are not alphabetically written in the notebook, then it takes a long time to find out every time. In the Algorithm class, you may have learned that this has a complexity of O(n). But if names are kept alphabetically, then a binary search can be used and it will take time (log n). You know that O (log n) takes less time than O(n).

Although O(log n) takes considerably less time, still, it takes some time. It would have been best if it would take no time at all. For this case, perhaps, you could memorize the names and prices of all the products and tell the price as soon as the buyer has a product name.

This exact scenario can be solved using HashMap. We can put the name of the products and their price in a HashMap andHashMap can return the value with a key in almost no time.

Now, let’s define what a HashMap  is.HashMapis a key-value data structure that provides constant time, O(1) complexity for both get and put operation.

Let's look at an example:

//create a map in java 11
var productPrice = new HashMap<String, Double>();

//or in java 8
Map<String, Double> productPrice = new HashMap<>();

// add value
productPrice.put("Rice", 6.9);
productPrice.put("Flour", 3.9);
productPrice.put("Sugar", 4.9);
productPrice.put("Milk", 3.9);
productPrice.put("Egg", 1.9);


Now, we need to access the price with the key (product name) from the map. For that, we have a method named get ().

//get value
Double egg = productPrice.get("Egg");
System.out.println("The price of Egg is: " + egg);


Now that we've covered the basics of HashMap, let’s go deep and how can we use it.

Printing All Keys and Values From the HashMap 

There are several ways to print all the keys and value from the hashmap. Let's see one by one - 

1. We want to print all the keys:

Set<String> keys = productPrice.keySet();
//print all the keys 
for (String key : keys) {
System.out.println(key);
}


Or

keys.forEach(key -> System.out.println(key));


I prefer theforEach loop with the lambda expression as it is more concise. 

2. We want to print all the following values:

Collection<Double> values = productPrice.values();
values.forEach(value -> System.out.println(value));


3. We want to print all the keys and values altogether, as shown below:

Set<Map.Entry<String, Double>> entries = productPrice.entrySet();

for (Map.Entry<String, Double> entry : entries) {
System.out.print("key: "+ entry.getKey());
System.out.println(", Value: "+ entry.getValue());
}


Or, we can use theforEach lambda expression, which is more concise:

productPrice.forEach((key, value) -> {
System.out.print("key: "+ key);
System.out.println(", Value: "+ value);
});


We Want to Know if a Key Already Exists 

Often times, it becomes the case that we first want to check if a key already exists or not. Based on the information, we must make a decision. For example, in dynamic programming, memorization is one of the techniques that we use most frequently. Let's check out an example.

The Fibonacci series is a famous series we use in case of demonstrating recursion. The formula of this series is as follows:

f(n)  = f(n-1) + f(n-2)


However, in this example, the same value may get calculated over and over, which can be easily prevented if we use memoization. 

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

public class Fibonacci {
    private Map<Integer, BigInteger> memoizeHashMap = new HashMap<>();
    {
        memoizeHashMap.put(0, BigInteger.ZERO);
        memoizeHashMap.put(1, BigInteger.ONE);
        memoizeHashMap.put(2, BigInteger.ONE);
    }

    private BigInteger fibonacci(int n) {
        if (memoizeHashMap.containsKey(n)) {
            return memoizeHashMap.get(n);
        } else {
            BigInteger result = fibonacci(n - 1).add(fibonacci(n - 2));
            memoizeHashMap.put(n, result);

            return result;
        }
    }

    public static void main(String[] args) {
        Fibonacci fibonacci = new Fibonacci();
        for (int i = 0; i < 100; i++) {
            System.out.println(fibonacci.fibonacci(i));
        }
    }
}


In this code, we have first checked if a Fibonacci number is already available in the memoizeHashMap or not. If it is already available, we don't need to calculate, we can just get it using the key. Otherwise, we can always calculate. 

The above code will produce 100 Fibonacci number faster.

Note: the put() method replaces the value with a key if the key already exists in the map. 

Now, let's look into some of the methods available in HashMap that can make our life easy.

Comparison: computeIfAbsent() Vs. puIfAbsent()

Now, let's revisit the fibonacci() method from the previous code block again. We can make it shorter and more concise if we use the computeIfAbsent() method instead of containsKey().  

private BigInteger fibonacci(int n) {

return memoizeHashMap.computeIfAbsent(n,
                (key) -> fibonacci(n - 1).add(fibonacci(n - 2)));
}


This method takes two arguments. One is the key and the other is a functional interface, which takes a key and, in turn, returns a value. The idea is, if the key exists in the map, it will return the value. Otherwise, it will compute the value and add it the map and then return the value. This makes the entire code much simpler and shorter. 

However, there is another method named putIfAbsent() that takes a value directly. 

productPrice.putIfAbsent("Fish", 4.5);


Differences Between putIfAbsent() and computeIfAbsent()  

computeIfAbsent() takes a mapping function, that is called to obtain the value if the key is missing. On the other hand, putIfAbsent()  takes the value directly. So in case, the value of the key comes from a method call and if the method is the expensive one, then, the computeIfAbsent() will not calculate the value unless the key is not found, where the putIfAbsent() will calculate the value anyway. 

var theKey = "Fish";        
//Even though if the key is present, the callExpensiveMethodToFindValue will get called
productPriceMap.putIfAbsent(theKey, callExpensiveMethodToFindValue(theKey)); 

//The callExpensiveMethodToFindValue will never get called if key is already present 
productPriceMap.computeIfAbsent(theKey, key -> callExpensiveMethodToFindValue(key)); 


Comparison: compute() Vs. computeIfPresent() 

Similarly, HashMap has methods named compute() and computeIfPresent(). 

We all know Oracle donated Java EE to the Eclipse Foundation, and consequently, it was renamed Jakarta EE. Let's say we want to write a program where we feed articles about this topic and calculate the frequency of select words to see how often people are mentioning these words. 

import java.util.HashMap;
import java.util.Map;

public class WordFrequencyFinder {

    private Map<String, Integer> map = new HashMap<>();

    {
        map.put("Java", 0);
        map.put("Jakarta", 0);
        map.put("Eclipse", 0);
    }

    public void read(String text) {
        for (String word : text.split(" ")) {
            if (map.containsKey(word)) {
                Integer value = map.get(word);
                map.put(word, ++value);
            }
        }
    }
}


The above code is too simple. We first checked if the key already exists in the map. If it exists, we can get the value and update it with an increment. This is the old way of writing code. 

Java 8 brings a nicer method called computeIfPresent(). Let's rewrite the read method with this method. 

public void read(String text) {
  for (String word : text.split(" ")) {
    map.computeIfPresent(word, (String key, Integer value) -> ++value);
  }
}


This above code is much nicer. The computeIfPresent() method takes the key and a remapping function, which, in turn, computes the value only if the key is present. So, the remapping function is only called if the key is present in the map, otherwise not. 

Furthermore, we have another method named compute(), which takes similar arguments as  computeIfPresent(). However, it computes the remapping function and it doesn't matter if the key is present or not. Based on the remapping function's output, it adds the value to the map. 

getOrDefault()

In some cases, it happens that the key we look at has a map that does not exist. However, we still want to have a value and we do not want to change the map. In such cases, we can use the methodgetOrDefault(), which is very useful.

productPriceMap.getOrDefault("Fish", 29.4);


Conclusion

HashMap makes the data access much easier and faster. And Java 8 and the introduction of lambda expressions make our life as developers much more simple. We can use the lambda expression to make our code shorter and concise. 



If you enjoyed this article and want to learn more about Java Collections, check out this collection of tutorials and articles on all things Java Collections.

Data structure Java (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • Floyd's Cycle Algorithm for Fraud Detection in Java Systems
  • Merge Multiple PDFs in MuleSoft
  • Scaling Java Microservices to Extreme Performance Using NCache
  • What Is a Jagged Array in Java With Examples?

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!