Java Hashmap Tutorial

Avatar

By squashlabs, Last Updated: Oct. 23, 2023

Java Hashmap Tutorial

Introduction to Hashmap

A HashMap is a data structure in Java that allows you to store and retrieve key-value pairs. It provides constant time complexity for basic operations like adding, removing, and retrieving elements. This makes it a popular choice for many applications where fast access to data is important.

Related Article: How to Use a Scanner Class in Java

Structure of a Hashmap

A HashMap is internally implemented as an array of linked lists. Each element in the array is called a bucket, and each bucket contains a linked list of key-value pairs. When you add a key-value pair to a HashMap, it calculates the index of the bucket using the hash code of the key. If multiple keys have the same hash code, they are stored in the same bucket as a linked list.

Creating a Hashmap

To create a HashMap in Java, you need to import the java.util.HashMap class. Here's an example of creating a HashMap and adding some key-value pairs:

import java.util.HashMap;public class Main {    public static void main(String[] args) {        HashMap<String, Integer> hashMap = new HashMap<>();        hashMap.put("apple", 10);        hashMap.put("banana", 5);        hashMap.put("orange", 8);    }}

In this example, we create a HashMap that stores String keys and Integer values. We then add three key-value pairs to the HashMap using the put() method.

Methods in Hashmap

HashMap provides various methods to manipulate and retrieve elements. Here are some commonly used methods:

- put(key, value): Adds a key-value pair to the HashMap.

- get(key): Retrieves the value associated with the specified key.

- remove(key): Removes the key-value pair associated with the specified key.

- containsKey(key): Checks if the HashMap contains a specific key.

- containsValue(value): Checks if the HashMap contains a specific value.

- size(): Returns the number of key-value pairs in the HashMap.

Related Article: How to Easily Print a Java Array

Adding Elements to a Hashmap

Adding elements to a HashMap is simple and efficient. You can use the put(key, value) method to add key-value pairs. Here's an example:

HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);

In this example, we add three key-value pairs to the HashMap. The keys are strings ("apple", "banana", "orange") and the values are integers.

Removing Elements from a Hashmap

Removing elements from a HashMap can be done using the remove(key) method. Here's an example:

HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);hashMap.remove("banana");

In this example, we remove the key-value pair with the key "banana" from the HashMap.

Accessing Elements in a Hashmap

You can access elements in a HashMap using the get(key) method. Here's an example:

HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);int appleQuantity = hashMap.get("apple");System.out.println(appleQuantity); // Output: 10

In this example, we retrieve the value associated with the key "apple" and store it in the appleQuantity variable.

Looping Through a Hashmap

You can iterate over the key-value pairs in a HashMap using various methods. Here's an example using a for-each loop:

HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);for (String key : hashMap.keySet()) {    int value = hashMap.get(key);    System.out.println(key + ": " + value);}

In this example, we loop through each key in the HashMap using the keySet() method. We retrieve the corresponding value using the get(key) method and print both the key and value.

Related Article: How to Implement a Delay in Java Using java wait seconds

Use Case: Storing User Information

HashMaps are often used to store user information in web applications. Here's an example of using a HashMap to store user details:

HashMap<Integer, User> userMap = new HashMap<>();// Creating user objectsUser user1 = new User(1, "John");User user2 = new User(2, "Jane");// Adding users to the HashMapuserMap.put(user1.getId(), user1);userMap.put(user2.getId(), user2);// Retrieving a user by IDUser retrievedUser = userMap.get(1);System.out.println(retrievedUser.getName()); // Output: John

In this example, we have a User class that represents a user with an ID and a name. We create two user objects and store them in the HashMap using their IDs as keys. We can then retrieve a user object by its ID.

Use Case: Counting Word Frequency

HashMaps can also be used to count the frequency of words in a text. Here's an example:

String text = "This is a sample text. This text contains some words. Some words may repeat.";HashMap<String, Integer> wordFrequencyMap = new HashMap<>();String[] words = text.split(" ");for (String word : words) {    wordFrequencyMap.put(word, wordFrequencyMap.getOrDefault(word, 0) + 1);}for (String word : wordFrequencyMap.keySet()) {    int frequency = wordFrequencyMap.get(word);    System.out.println(word + ": " + frequency);}

In this example, we split the text into an array of words using the split() method. We then iterate over each word, adding it to the HashMap and incrementing its count. Finally, we loop through the HashMap and print the word and its frequency.

Best Practice: Using Generics

It is considered a best practice to use generics when working with HashMaps to ensure type safety. Here's an example:

HashMap<String, Integer> hashMap = new HashMap<>();

In this example, we specify that the keys of the HashMap are strings and the values are integers. This allows the compiler to enforce type safety and prevents runtime errors.

Best Practice: Avoiding Null Keys and Values

It is generally recommended to avoid using null as keys or values in a HashMap. While it is technically allowed, it can lead to unexpected behavior and null pointer exceptions. Instead, consider using sentinel values or redesigning your code to handle such scenarios more robustly.

Related Article: Multiple Inheritance In Java: How to Use

Real World Example: Implementing a Phone Directory

A real-world example of using a HashMap is implementing a phone directory. Here's an example:

HashMap<String, String> phoneDirectory = new HashMap<>();phoneDirectory.put("John Smith", "555-1234");phoneDirectory.put("Jane Doe", "555-5678");String johnsNumber = phoneDirectory.get("John Smith");System.out.println(johnsNumber); // Output: 555-1234

In this example, we use a HashMap to store names as keys and phone numbers as values. We can easily retrieve a phone number by providing the name.

Real World Example: Creating a Shopping Cart

Another real-world example of using a HashMap is creating a shopping cart. Here's an example:

HashMap<String, Integer> shoppingCart = new HashMap<>();// Adding items to the shopping cartshoppingCart.put("Apple", 2);shoppingCart.put("Banana", 3);shoppingCart.put("Orange", 1);// Updating the quantity of an itemshoppingCart.put("Apple", shoppingCart.getOrDefault("Apple", 0) + 1);// Removing an item from the shopping cartshoppingCart.remove("Banana");// Retrieving the total number of items in the shopping cartint totalItems = shoppingCart.values().stream().mapToInt(Integer::intValue).sum();System.out.println(totalItems); // Output: 6

In this example, we use a HashMap to store items as keys and quantities as values. We can easily add, update, and remove items from the shopping cart. We can also calculate the total number of items in the cart by summing up the quantities.

Performance Consideration: Initial Capacity and Load Factor

When creating a HashMap, you can specify an initial capacity and a load factor. The initial capacity is the number of buckets created when the HashMap is constructed. The load factor determines when the HashMap is resized. It is a value between 0 and 1, where 1 means the HashMap is resized when it is 100% full. Adjusting these parameters can impact the performance of the HashMap based on the expected number of key-value pairs and the rate of growth.

Performance Consideration: Hashing Function

The performance of a HashMap is heavily dependent on the quality of the hashing function used to calculate the index of the bucket. A good hashing function distributes the keys evenly across the buckets, reducing collisions and improving performance. Java's built-in hashing function for objects calculates the hash code based on the memory address of the object, but you can override this behavior by implementing the hashCode() method in your key objects.

Related Article: Java Printf Method Tutorial

Advanced Technique: Custom Key Objects

By default, HashMap uses the hashCode() and equals() methods of the key objects to determine equality and calculate the bucket index. If you want to use custom objects as keys, you need to override these methods to ensure correct behavior. Here's an example:

class Person {    private String name;    private int age;    // constructor, getters, setters    @Override    public int hashCode() {        return Objects.hash(name, age);    }    @Override    public boolean equals(Object obj) {        if (this == obj) {            return true;        }        if (obj == null || getClass() != obj.getClass()) {            return false;        }        Person person = (Person) obj;        return age == person.age && Objects.equals(name, person.name);    }}

In this example, we override the hashCode() and equals() methods in the Person class to ensure that two Person objects with the same name and age are considered equal.

Advanced Technique: Concurrent Access

If multiple threads access a HashMap concurrently, there may be synchronization issues and data inconsistencies. Java provides a synchronized version of HashMap called ConcurrentHashMap, which ensures thread-safety and handles concurrent access gracefully. If you need to work with concurrent access, consider using ConcurrentHashMap instead.

Code Snippet: Insertion of Elements

Here's a code snippet demonstrating the insertion of elements into a HashMap:

HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);

In this example, we create a HashMap and add three key-value pairs using the put() method.

Code Snippet: Deletion of Elements

Here's a code snippet demonstrating the deletion of elements from a HashMap:

HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);hashMap.remove("banana");

In this example, we remove the key-value pair with the key "banana" from the HashMap using the remove() method.

Related Article: How to Fix the java.lang.reflect.InvocationTargetException

Code Snippet: Retrieval of Elements

Here's a code snippet demonstrating the retrieval of elements from a HashMap:

HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);int appleQuantity = hashMap.get("apple");System.out.println(appleQuantity); // Output: 10

In this example, we retrieve the value associated with the key "apple" using the get() method.

Code Snippet: Iterating over Entries

Here's a code snippet demonstrating how to iterate over the key-value pairs in a HashMap:

HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {    String key = entry.getKey();    int value = entry.getValue();    System.out.println(key + ": " + value);}

In this example, we use the entrySet() method to obtain a set of key-value pairs. We then iterate over each entry and retrieve the key and value.

Code Snippet: Sorting Hashmap by Keys or Values

Here's a code snippet demonstrating how to sort a HashMap by keys or values:

Sorting by keys:

HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);TreeMap<String, Integer> sortedMap = new TreeMap<>(hashMap);for (Map.Entry<String, Integer> entry : sortedMap.entrySet()) {    String key = entry.getKey();    int value = entry.getValue();    System.out.println(key + ": " + value);}

Sorting by values:

HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);List<Map.Entry<String, Integer>> sortedList = new ArrayList<>(hashMap.entrySet());sortedList.sort(Map.Entry.comparingByValue());for (Map.Entry<String, Integer> entry : sortedList) {    String key = entry.getKey();    int value = entry.getValue();    System.out.println(key + ": " + value);}

In both examples, we use a TreeMap to sort the HashMap by keys or a sorted list to sort by values. We then iterate over the sorted entries and print the key-value pairs.

Error Handling: Null Pointer Exceptions

When working with HashMaps, you need to be mindful of null keys and null values. If you try to access a non-existent key or value, a null pointer exception may occur. To avoid this, you can use the containsKey(key) or containsValue(value) methods to check if a key or value exists before accessing it.

Related Article: How to Resolve java.lang.ClassNotFoundException in Java

Error Handling: Concurrent Modification Exceptions

If you modify a HashMap while iterating over it using an iterator, a concurrent modification exception may occur. To avoid this, consider using the Iterator or ListIterator methods provided by the keySet(), entrySet(), or values() methods to safely iterate over the HashMap.

This concludes the Java HashMap tutorial. You have learned about the basics of HashMap, its structure, methods, and various use cases. You have also explored best practices, performance considerations, advanced techniques, code snippets, and error handling.

Can Two Java Threads Access the Same MySQL Session?

Sharing a MySQL session between two Java threads can introduce concurrency issues and potential data inconsistencies. This article explores the chall… read more

How to Define and Use Java Interfaces

Learn how to use and implement interfaces in Java with this tutorial. The article covers topics such as defining an interface, implementing interface… read more

Java Constructor Tutorial

Java constructors are an essential part of object-oriented programming. They allow you to initialize objects and perform necessary setup tasks. This … read more

Java Exception Handling Tutorial

Exception handling is a critical aspect of Java programming. This tutorial will guide you through the basics of exception handling, including the hie… read more

Overriding vs Overloading in Java: Tutorial

Learn the differences between overriding and overloading in Java with this tutorial. This article covers best practices, performance considerations, … read more

How To Fix the "java.lang.NoClassDefFoundError" Error

Java developers often encounter the "java.lang.NoClassDefFoundError" error, which can prevent their code from running smoothly. This article provides… read more

How to Handle Java's Lack of Default Parameter Values

Java is a powerful programming language, but it lacks default parameter values. This article explores methods to manage this limitation, including me… read more

How To Convert String To Int In Java

How to convert a string to an int in Java? This article provides clear instructions using two approaches: Integer.parseInt() and Integer.valueOf(). L… read more

How to Retrieve Current Date and Time in Java

Obtain the current date and time in Java using various approaches. Learn how to use the java.util.Date class and the java.time.LocalDateTime class to… read more

Java Hibernate Interview Questions and Answers

Hibernate is a popular object-relational mapping (ORM) tool in Java development. In this article, we will explore Hibernate interview questions and a… read more