HashMap in Java: A Detailed Explanation

HashMap in Java: A Detailed Explanation

10 Sep 2024
Beginner
568 Views
30 min read
Learn with an interactive course and practical hands-on labs

Java Online Course Free with Certificate

HashMap in Java

HashMap in Java has been a crucial part of Java's collection framework since version 1.2, which can be found in the java.util.package. It offers a simple implementation of Java's Map interface. In Java, HashMap holds data in (Key, Value) pairs that may be accessed using an index of another type (for example, an integer). One item serves as a key (index) to another (value). If you try to enter a duplicate key into HashMap, it will replace the element for the associated key.

In this Java tutorial, we will learn about HashMap in Java, including its hierarchy, creating a HashMap, Java HashMap Constructors, adding and accessing elements, iterating over a HashMap, HashMap vs. TreeMap vs. LinkedHashMap, and many more.

Take your career to the next level by joining our comprehensive Java Full Stack Developer Certification Training today!

What is HashMap in Java?

HashMap in Java is a data structure that is part of the Java Collections Framework and is used for storing key-value pairs, where each key is unique. It is similar to the hash table, but it is not synchronized. It allows us to store null elements as well, but there should be only one null key object, and there can be any number of null values. Let's dive into some important points about HashMap:

  • Save data in key-value pairs, where each key is unique.
  • To allow efficient access, a hashing technique is used, with get() and put() operations often taking O(1) time.
  • Does not assure the order of elements, as the order can change over time.
  • Allow one null key and multiple null values.
  • It is not thread-safe and requires external synchronization for concurrent access.
  • Dynamically increases its size when the number of elements exceeds a certain threshold to maintain performance.
  • Manages hash collisions using linked lists or binary trees within the buckets.
Read More
Java Full Stack Development Roadmap
OOPs Concepts in Java: Encapsulation, Abstraction, Inheritance, Polymorphism

Hierarchy of HashMap in Java

Creating and Using HashMap in Java

Creating and using a HashMap in Java involves instantiating the map with specified key-value types and then performing operations like adding, retrieving, and removing entries. This allows for efficient data management and quick access based on unique keys.

1. Creating a HashMap

To create a HashMap, we first have to import the java.util.HashMap package. After we import the package, we can create a HashMap in Java.

Syntax

 // creating a HashMap
 HashMap<KeyType, ValueType> mapName = new HashMap<>();

2. Adding Elements in Hashmap

To add the elements in HashMap in Java, we should use the put() method. The syntax for adding elements in Hashmap is given below;

Syntax

 HashMap<KeyType, ValueType> mapName = new HashMap<>();
 //Adding elements in the HashMap
 map.put(key, value);

Example

Let's understand an example of how to create and add elements in the HashMap;

 import java.util.HashMap;

 class Main {
  public static void main(String[] args) {
    // create a hashmap
        HashMap languages = new HashMap<>();
    // add elements to hashmap
        languages.put("Java", 8);
        languages.put("JavaScript", 1);
        languages.put("Python", 3);
        System.out.println("HashMap: " + languages);
     }
  }

Output

HashMap: {Java=8, JavaScript=1, Python=3}   

Java HashMap Constructors

A HashMap constructor in Java is a special function that helps you create and set up a new HashMap. It decides the starting size, how full the map can get before it grows, and whether it should start with items copied from another map. The HashMap class offers various constructors that let you customize how your map is set up, like choosing the starting size or copying items from another map.
  1. HashMap()
  2. HashMap(int initialCapacity)
  3. HashMap(int initialCapacity, float load factor)
  4. HashMap(Map map)

1. HashMap()

It is also called the default constructor, which initializes a HashMap with a starting capacity of 16 and a load factor of 0.75.

Syntax

   HashMap<KeyTalue, ValueType> mapName = new HashMap();

Example

import java.util.HashMap;

  public class Main {
  public static void main(String[] args) {
      // Create a new HashMap using the default constructor
      HashMap<String, Integer> map = new HashMap<>();

      // Add some key-value pairs to the HashMap
      map.put("Apple", 1);
      map.put("Banana", 2);
      map.put("Cherry", 3);

    // Print the HashMap
     System.out.println(map);
   }
  }

Output

{Apple=1, Banana=2, Cherry=3}

2. HashMap(int initialCapacity)

The HashMap(int initialCapacity) constructor generates a HashMap with a given initial capacity and 0.75 load factor. This implies that the HashMap will begin with a set number of buckets, which might assist in improving efficiency if you know roughly how many items will be stored.

Syntax

  HashMap<KeyType, ValueType> mapName = new HashMap<>(int initialCapacity);

Example

 import java.util.HashMap;

  public class Main {
  public static void main(String[] args) {
     // Create a HashMap with an initial capacity of 20
     HashMap<String, Integer> map = new HashMap<>(20);

     // Add some key-value pairs to the HashMap
     map.put("Apple", 1);
     map.put("Banana", 2);
     map.put("Cherry", 3);
     map.put("Date", 4);

     // Print the HashMap
     System.out.println(map);
      }
    }   

Output

{Apple=1, Banana=2, Cherry=3, Date=4}

3. HashMap(int initialCapacity, float load factor)

The HashMap (int initialCapacity, float load factor) constructor in Java creates a HashMap with a specified initial capacity and load factor. This allows you to set both the HashMap's beginning size and its sensitivity to how full it is before resizing.

Syntax

HashMap<KeyType, ValueType> map = new HashMap<>(int initialCapacity, float loadFactor);

Example

 import java.util.HashMap;

   public class Main {
   public static void main(String[] args) {
     // Create a HashMap with an initial capacity of 10 and a load factor of 0.5
     HashMap<String, Integer> map = new HashMap<>(10, 0.5f);

     // Add some key-value pairs to the HashMap
     map.put("Apple", 1);
     map.put("Banana", 2);
     map.put("Cherry", 3);
     map.put("Date", 4);

     // Print the HashMap
     System.out.println(map);
    }
  }

Output

{Apple=1, Banana=2, Cherry=3, Date=4}

4. HashMap(Map map)

The HashMap(Map<? extends K, ? extends V> m) constructor in Java creates a new HashMap that initializes its content with the entries from the specified map. This constructor is useful when you want to create a HashMap that is a copy of another map.

Syntax

HashMap<KeyType, ValueType> map = new HashMap<>(Map<? extends KeyType, ? extends ValueType> m);        

Example

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

 public class Main {
   public static void main(String[] args) {
       // Create an existing map with some entries
       Map<String, Integer> originalMap = new HashMap<>();
       originalMap.put("Apple", 1);
       originalMap.put("Banana", 2);
       originalMap.put("Cherry", 3);

      // Create a new HashMap by copying the entries from the original map
      HashMap<String, Integer> copiedMap = new HashMap<>(originalMap);

      // Print the copied HashMap
      System.out.println(copiedMap);
      }
  }

Output

{Apple=1, Banana=2, Cherry=3}    
Read More
Constructor Chaining in Java
for Loop in Java: Its Types and Examples
do...while Loop in Java - Flowchart & Syntax

Some Operations on HashMap

There are various types of operations are performed on HashMap, but we will look into some basic operations that are mostly performed in Hashmap:
  1. Adding Elements in HashMap
  2. Change Elements in HashMap
  3. Remove Elements in HashMap
  4. Iterating over a HashMap

    1. Adding and Accessing Elements in HashMap

    The HashMap(int initialCapacity) constructor generates a HashMap with a given initial capacity and 0.75 load factor. This implies that the HashMap will begin with a set number of buckets, which might assist in improving efficiency if you know roughly how many items will be stored.

    Example

     import java.util.HashMap;
    
     public class Main {
     public static void main(String[] args) {
         // Creating a HashMap
         HashMap<String, Integer> map = new HashMap<>();
    
         // Adding elements to the HashMap
         map.put("Apple", 10);
         map.put("Banana", 20);
         map.put("Orange", 30);
         System.out.println(map);
    
         // Accessing elements in the HashMap
         String key = "Banana";
         Integer value = map.get(key);
    
         // Checking if the key exists in the HashMap
         if (value != null) {
             System.out.println("Value for key \"" + key + "\" is: " + value);
         } else {
             System.out.println("Key \"" + key + "\" not found in the HashMap.");
         }
        }
       }
    

    Output

     {Apple=10, Orange=30, Banana=20}
      Value for key "Banana" is: 20   
    Note:We can also access the keys, values, and key/value pairs of the hashmap as set views using keySet(), values(), and entrySet() methods, respectively.

    Example

    import java.util.HashMap;
    
     class Main {
      public static void main(String[] args) {
       HashMap<Integer, String> languages = new HashMap<>();
       languages.put(1, "Java");
       languages.put(2, "Python");
       languages.put(3, "JavaScript");
       System.out.println("HashMap: " + languages);
       // return set view of keys
       // using keySet()
       System.out.println("Keys: " + languages.keySet());
    
       // return set view of values
       // using values()
       System.out.println("Values: " + languages.values());
    
       // return set view of key/value pairs
       // using entrySet()
       System.out.println("Key/Value mappings: " + languages.entrySet());
       }
      }
    

    Output

    HashMap: {1=Java, 2=Python, 3=JavaScript}
    Keys: [1, 2, 3]
    Values: [Java, Python, JavaScript]
    Key/Value mappings: [1=Java, 2=Python, 3=JavaScript]    

    2. Change Elements in HashMap

    To modify an element in a HasMap in Java, use the put() function. If the key already exists in the HashMap, the put() function updates the value associated with it. If the key is not there, a new key-value pair will be created.

    Example

     import java.util.HashMap;
    
      public class FruitInventory {
       public static void main(String[] args) {
         // Create a HashMap to store fruit quantities
         HashMap<String, Integer> fruitQuantities = new HashMap<>();
    
         // Add some fruits and their quantities to the HashMap
         fruitQuantities.put("Apple", 10);
         fruitQuantities.put("Banana", 20);
         fruitQuantities.put("Orange", 15);
    
         // Print the original HashMap
         System.out.println("Original fruit quantities: " + fruitQuantities);
    
         // Update the quantity of Apples
         fruitQuantities.put("Apple", 25);
    
         // Print the updated HashMap
         System.out.println("Updated fruit quantities: " + fruitQuantities);
         }
      }
    

    Output

     Original fruit quantities: {Apple=10, Banana=20, Orange=15}
     Updated fruit quantities: {Apple=25, Banana=20, Orange=15}  

    3. Remove Element in HashMap

    To remove an element from a HashMap in Java, use the remove() function. The remove() function accepts the key of the element you wish to delete as an argument.

    Example

    import java.util.HashMap;
    
     public class RemoveElement {
      public static void main(String[] args) {
         // Create a HashMap to store some fruit quantities
       HashMap fruitQuantities = new HashMap<>();
    
         // Add some fruits and their quantities to the HashMap
           fruitQuantities.put("Apple", 10);
           fruitQuantities.put("Banana", 20);
           fruitQuantities.put("Orange", 15);
    
           // Print the original HashMap
            System.out.println("Original fruit quantities: " + fruitQuantities);
    
          // Remove "Banana" from the HashMap
            fruitQuantities.remove("Banana");
    
          // Print the updated HashMap
       System.out.println("Updated fruit quantities after removing Banana: " + fruitQuantities);
        }
      }
    

    Output

     Original fruit quantities: {Apple=10, Banana=20, Orange=15}
     Updated fruit quantities after removing Banana: {Apple=10, Orange=15}   

    4. Iterating over a Hashmap

    Iterating over a HashMap means going through each key-value pair stored in the HashMap and performing operations on them, such as reading their contents, altering them, or utilizing them in some logic. We utilize Java for each loop to iterate over keys only, values only, and key/value mapping.

    Example

     import java.util.HashMap;
     import java.util.Map.Entry;
    
     class Main {
      public static void main(String[] args) {
    
       // create a HashMap
       HashMap<Integer, String> languages = new HashMap<>();
       languages.put(1, "Java");
       languages.put(2, "Python");
       languages.put(3, "JavaScript");
       System.out.println("HashMap: " + languages);
    
       // iterate through keys only
       System.out.print("Keys: ");
       for (Integer key : languages.keySet()) {
         System.out.print(key);
        System.out.print(", ");
       }
    
      // iterate through values only
       System.out.print("\nValues: ");
        for (String value : languages.values()) {
         System.out.print(value);
          System.out.print(", ");
       }
        
        // iterate through key/value entries
       System.out.print("\nEntries: ");
       for (Entry entry : languages.entrySet()) {
         System.out.print(entry);
         System.out.print(", ");
          }
        }
      }
    

    Output

     HashMap: {1=Java, 2=Python, 3=JavaScript}
     Keys: 1, 2, 3,
     Values: Java, Python, JavaScript,        
     Entries: 1=Java, 2=Python, 3=JavaScript,    

    The Internal structure of HashMap

    HashMap in Java stores the elements using key-value mapping, where we can fetch an element from the HashMap using its key. Let's understand HashMap structure in some key points.

    • As seen in the node form above, a node is structured similarly to a linked list node. A bucket refers to an array of these nodes. HashMap holds elements in buckets, the number of which is referred to as capacity.
    • When we add a value to the map, the key's hashCode() function determines which bucket it will be kept in. Essentially, a hash value is calculated using the key's hash code. This hash value is used to compute the index in the array where the Entry object will be stored.
    • When we try to get the item, the HashMap creates the bucket in the same way: by using hashCode(), which calculates the initial index position. Then, in that bucket, it iterates through the discovered objects, using the key's equals() function to locate an exact match.
    • To avoid having a large number of buckets with various values, the capacity is increased if 75% (the load factor) of the buckets are not empty. The baseline load factor is 75%, and the starting capacity is 16. Both may be set in the constructor, as previously described.

    Performance of HashMap

    The performance of Hashmap depends on 4 factors that are explained below:

    1. Initial Capacity
    2. Load Factor
    3. Threshold
    4. Rehashing

    1. Initial Capacity

    It refers to the capacity of a HashMap at the moment of formation. In Java, the initial value is 2^4=16, indicating that it can retain 16 key-value pairs.

    2. Load factor

    It is the percentage value of the capacity, after which the Hashmap capacity will be enhanced. In Java, it is set to 0.75f by default, which means that rehashing occurs once 75% of the capacity is filled.

    3. Threshold

    It is the product of the load factor and the initial capacity. In Java, the default is (16 * 0.75 = 12). That is, Rehashing occurs after entering 12 key-value pairs into the HashMap.

    4. Rehasing

    It is the process of doubling the capacity of a HashMap after it has reached its Threshold. In Java, HashMap rehashes (by default) in the following sequence: 2^4, 2^5, 2^6, 2^7, and so on.

    Advanced Features and Best Practices

    Features of HashMap

    Here are the advanced features of HashMap in Java:

    • Stores data in key-value pairs for efficient retrieval by key.
    • Utilizes a hash function to provide average O(1) time complexity for operations.
    • Manages collisions using linked lists or trees within buckets.
    • Automatically resizes and rehashes when the load factor threshold is exceeded.
    • Support one null key and multiple null values with unordered iterations.

    Comparing HashMap - HashMap vs. TreeMap vs. LinkedHashMap

    The key differences between Hashmap, TreeMap, and LinkedHashmap are depicted below:
    FeaturesHashMapTreeMapLinkedHashMap
    OrderNo specific orderSorted by keyInsertion or access order
    ImplementationHash tableRed-Black TreeHash table + linked list
    Time ComplexityO(1) average, O(n) worstO(log n)O(1) average
    Null Keys/ValuesOne null key, multiple null valuesNo null keys, multiple null valuesOne null key, multiple null values
    Use CaseFast lookups, unordered dataSorted keys, range queriesPredictable iteration order

    Real-World Applications and Use Cases of HashMap

    HashMap is a versatile data structure with a range of real-world applications and use cases due to its efficiency and flexibility. Here are some common scenarios where HashMap is particularly useful:

    1. Caching Data

    Storing frequently accessed data to improve performance by reducing repeated computations or database queries.

    2. Counting Occurrences

    Counting word frequencies in a text file or counting occurrences of specific events in logs.

    3. Lookup Tables

    Creating fast lookup tables for quick access to data based on unique keys.

    4. Implementing Indexes

    Building indexes for databases or data structures to provide quick access to records based on certain keys.

    5. Graph Representations

    Representing graphs where nodes can be mapped to adjacency lists or other structures.

    6. Job Scheduling

    Managing job queues or scheduling tasks based on unique identifiers.

    Conclusion
    In this article, we have covered the essential aspects of HashMap in Java, including its structure, performance, and various features. HashMap is a key-value storage mechanism that offers average O(1) time complexity for basic operations like get(), put(), and remove(), making it a powerful tool for scenarios requiring fast data retrieval. To become a full-stack developer, ScholorHat provides a full-stack Java Developer Certification Training Course that will help you on your journey to becoming a Java Developer.

    FAQs

    HashMap and HashSet are both part of the Java Collections Framework;
    • HashMap stores key-value pairs allows unique keys with duplicate values and is used for data retrieval based on keys. 
    • HashSet stores unique elements does not allow duplicates and is used when you need a collection of unique items. 

    The Map is an interface, and HashMap is a class of the Java collection framework. The Map interface can be implemented by using its implementing classes. In comparison, the HashMap class implements the Map interface. The Map contains unique key-pair values.

    HashMap stores key and value pairs, and it does not allow duplicate keys. If the key is duplicate, then the old key is replaced with the new value. Dummy value: In HashMap, there is no concept of dummy value; HashSet internally uses HashMap to add elements.

    The put method adds a value to the map under a given key. If the key doesn't exist, it creates a new entry with an empty list and then adds the value to that list. This makes it easy to store and manage multiple values associated with the same key in the map.
    Share Article
    About Author
    Shailendra Chauhan (Microsoft MVP, Founder & CEO at Scholarhat by DotNetTricks)

    Shailendra Chauhan, Founder and CEO of ScholarHat by DotNetTricks, is a renowned expert in System Design, Software Architecture, Azure Cloud, .NET, Angular, React, Node.js, Microservices, DevOps, and Cross-Platform Mobile App Development. His skill set extends into emerging fields like Data Science, Python, Azure AI/ML, and Generative AI, making him a well-rounded expert who bridges traditional development frameworks with cutting-edge advancements. Recognized as a Microsoft Most Valuable Professional (MVP) for an impressive 9 consecutive years (2016–2024), he has consistently demonstrated excellence in delivering impactful solutions and inspiring learners.

    Shailendra’s unique, hands-on training programs and bestselling books have empowered thousands of professionals to excel in their careers and crack tough interviews. A visionary leader, he continues to revolutionize technology education with his innovative approach.
    Accept cookies & close this