In Java, one of the most popular data structures you can find is a HashMap. HashMap allows you to store elements as key-value pairs. It is part of the Java Collections Framework and permits data retrieval with the use of unique keys.
The key advantage of HashMap is its performance, offering constant time complexity for basic operations like adding, removing, and fetching elements. This makes it a preferred choice for managing large datasets.
In this blog, we’ll cover everything about HashMap, including its hierarchy, constructors, features, and operations.
What is a HashMap?
A HashMap in Java is part of the Java Collections Framework and is used to store data in key-value pairs. It allows for efficient data retrieval through particular keys, wherein each key maps to one precise value. This structure makes HashMap a popular choice for scenarios where fast access to data is needed.
The HashMap class implements the Map Interface and uses hashing to store and manage elements. Internally, it uses an array of linked lists (or binary trees in case of high collisions) to store entries. The position of the key-value pair inside the HashMap is determined by the hash code of the key which ensures that retrieval is efficient.
Being part of the Java Collections Framework, HashMap offers various methods to carry out operations like insertion, deletion, and retrieval, making it fairly beneficial for dealing with large datasets.
Get curriculum highlights, career paths, industry insights and accelerate your technology journey.
Download brochure
HashMap Constructors
HashMap in Java provides several constructors to initialise the map in different ways. Here are the constructors available:
HashMap()
This creates an empty HashMap with some default capacity and load factor to use the constructor HashMap() itself.
HashMap<K, V> map = new HashMap<>();
HashMap(int initialCapacity)
This constructor creates a HashMap with a specified preliminary capacity. The load factor stays at the default 0.75.
HashMap<K, V> map = new HashMap<>(int initialCapacity);
HashMap(int initialCapacity, float loadFactor)
This constructor lets you outline both the initial capacity and the load factor. The load factor controls how you can get the full map earlier than it’s resized.
HashMap<K, V> map = new HashMap<>(int initialCapacity, float loadFactor);
HashMap(Map<? extends K, ? extends V> m)
This constructor helps you to initialise a new HashMap with the same mappings as the specified map.
To use HashMap in Java, you have to import the java.util.HashMap package first. Then, you can use this package to get all the essential methods and functionalities required for using the HashMap. Without this import, Java will not recognize the HashMap class.
import java.util.HashMap;
General Syntax for Creating a HashMap
You can create a HashMap with any type of key and value. The general syntax for creating a HashMap is:
HashMap<KeyType, ValueType> mapName = new HashMap<>();
KeyType: In this, you can define the data type of your keys. For example, String, Integer, etc.
ValueType: With the ValueType, you can define any data type of the values like some Integer or String, etc.
mapName: The variable name used to refer to the HashMap.
Example of Creating a HashMap
Here’s an example in which we will be creating a HashMap with the help of String. Here, the string works as the key type and Integer as a value and we can store it as key-value pairs. In this case, we can store some results as keys and their portions as values.
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
// Creating a HashMap with String as keys and Integer as values
HashMap<String, Integer> fruitMap = new HashMap<>();
// Adding elements to the HashMap
fruitMap.put("Apple", 5);
fruitMap.put("Banana", 12);
fruitMap.put("Orange", 8);
// Printing the HashMap
System.out.println(fruitMap);
}
}
Explanation
We first import the HashMap class.
We then declare and initialise a HashMap called fruitMap with String as the key type and Integer as the value type.
We use the put() method to add key-value pairs to the HashMap.
Finally, the System.out.println(fruitMap); statement prints the content of the HashMap.
Output
The output of the above code will be:
{Apple=5, Banana=12, Orange=8}
This output shows the keys (fruit names) and their corresponding values (quantities) stored in the HashMap.
Important Features of HashMap in Java
Key-Value Pairs: HashMap can store data inside the particular format of key-value pairs, wherein each key is unique, and every key is related to exactly one value.
No Duplicates for Keys: Only unique keys are allowed. If you try to insert a duplicate key, the new value will replace the old one.
Allows Null Values: HashMap allows one null key and multiple null values.
Not Ordered: HashMap does not maintain any order of the keys or values. The order may change when elements are added or removed.
Implements Map Interface: HashMap is part of the Java Collections Framework and implements the Map interface, imparting diverse methods for key-value pair operations.
Constant Time Performance: Basic operations such as inserting, retrieving, and deleting elements have an average time complexity of O(1), thanks to hashing.
Load Factor and Resizing: HashMap resizes automatically when the number of elements exceeds the product of the load factor and the initial capacity.
Non-Synchronized: HashMap is not thread-safe, meaning it is not synchronised. For multi-threaded environments, you should use ConcurrentHashMap or synchronise it manually.
Custom Load Factor and Capacity: You can create a HashMap with custom preliminary capacity and load factor to manipulate its performance.
Efficient Search: It makes use of hashing, which guarantees speedy lookups based on the key, making it highly efficient for massive datasets.
HashMap in Java allows you to carry out a number of operations, such as adding, accessing, updating, and putting off factors. Below, we will explore each operation with examples and explanations.
Add Elements
To add elements to a HashMap, you use the put() method, which associates the required value with the given key. If the key already exists, the value is set up to date.
Example
In this case, we are going to create a HashMap function and also give the key-value pairs, “Apple” and “Banana,” with their corresponding quantities through the use of the put() method.
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("Apple", 10);
map.put("Banana", 20);
System.out.println(map);
}
}
Output
{Apple=10, Banana=20}
Access Elements
If you need to access the elements which are inside a HashMap, you just need to use the get() method. This method will allow you to retrieve the value associated with a given key. If there is no key exists, then it returns null.
Example
In this example, the value associated with “Apple” is retrieved using the get() method. Since “Orange” doesn’t exist, null is returned.
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("Apple", 10);
System.out.println(map.get("Apple"));
System.out.println(map.get("Orange"));
}
}
Output
10
null
Change Elements
You can modify elements in a HashMap by using the put() method with an existing key. This will replace the old value with the new one.
Example
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("Apple", 10);
map.put("Apple", 15); // Changing the value for "Apple"
System.out.println(map);
}
}
Output
{Apple=15}
Remove Elements
Here, you can use the remove() method in order to remove a key-value pair from any HashMap. You just need to specify the key.
Example
In this example, we add two entries and then remove the one with the key “Apple” using the remove() method.
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("Apple", 10);
map.put("Banana", 20);
map.remove("Apple"); // Removing the entry for "Apple"
System.out.println(map);
}
}
Output
{Banana=20}
Get the Size of the HashMap
You have to use the size() method to get the total number of key-value pairs in the HashMap.
Example
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("Apple", 10);
map.put("Banana", 20);
System.out.println(map.size());
}
}
Output
2
Iterate Through HashMap
To iterate through a HashMap, you can use various methods such as forEach, entrySet(), or keySet(). This allows you to go through all the key-value pairs in the map.
Example
Here, you can implement the entrySet() method to iterate all over the HashMap and print each of its key-valueQ pairs.
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("Apple", 10);
map.put("Banana", 20);
for (HashMap.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
Output
Apple = 10
Banana = 20
Creating HashMap from Other Maps
You can create a HashMap from another map using the constructor that accepts a Map object. This copies all the entries from the provided map into the new HashMap.
Example
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> oldMap = new HashMap<>();
oldMap.put("Apple", 10);
oldMap.put("Banana", 20);
HashMap<String, Integer> newMap = new HashMap<>(oldMap);
System.out.println(newMap);
}
}
Output
{Apple=10, Banana=20}
Null as the Key
HashMap allows one null key. If you try to insert multiple null keys, only the last one will be kept. However, it allows multiple null values.
Example
Here, you must use null as a key twice, but only for the last value, i.e. 200 is retained for the null key.
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put(null, 100);
map.put("Banana", 20);
map.put(null, 200); // The previous null key entry is replaced
System.out.println(map);
}
}
Output
{null=200, Banana=20}
Performance of HashMap
HashMap performs most operations efficiently due to its use of hashing. Here are the key factors affecting its performance:
Fast Lookups
HashMap provides quick access to elements using unique keys. Here, you can store and retrieve data very quickly in HashMap, and this makes it very ideal for the cases where you need fast lookups.
Collision Handling
Regarding key collisions (when two keys have the same hash code), HashMap uses a linked list or a binary tree (from Java 8 onward) to manage multiple entries in the same bucket. This ensures that performance remains stable even with collisions.
Load Factor
The load factor controls when the HashMap needs to resize. By default, a load factor of 0.75 is used, which balances memory usage and performance. This prevents frequent resizing but ensures the map remains efficient as it grows.
Resizing
When the HashMap exceeds its full capacity, it resizes by doubling the size and then redistributing elements into new buckets. Although resizing is steeply-priced, it occurs now and again to limit its impact on overall performance.
Overall, HashMap offers reliable and fast performance for storing and accessing large amounts of data.
Insertion is typically constant time unless collisions occur. If multiple keys hash to the same bucket, the time complexity may degrade, but Java 8+ improves performance by using balanced trees in case of frequent collisions.
Access (get())
O(1)
O(n)
Accessing elements is normally constant time. However, in the worst case, if many elements hash to the same bucket, it could degrade to O(n). Java 8+ also uses trees to minimise this issue.
Remove (remove())
O(1)
O(n)
Removing elements is generally done in constant time. Collisions may increase the time in the worst case.
Contains Key (containsKey())
O(1)
O(n)
Checking for a key is typically fast, but again, collisions may cause slower performance in rare cases.
Size (size())
O(1)
O(1)
Finding the size of the HashMap is always done in constant time.
Iterate (entrySet())
O(n)
O(n)
Iterating over the HashMap requires going through all the elements, so the complexity is linear with respect to the number of entries.
Internal Structure of HashMap
Buckets
HashMap uses an array of nodes called buckets. Each bucket holds a list of entries (key-value pairs). The bucket index is determined by the hash code of the key, allowing the HashMap to organise data efficiently.
Hashing
When you insert a key-value pair, the hashCode() method for any key generates a hash code. This hash code is used to calculate the index of the bucket in which the pair could be stored. The key determines the position, making lookups speedy.
Collision Handling
If two keys generate the same hash code, a collision occurs. HashMap handles collisions using a linked list in earlier versions of Java and a binary tree when collisions are too frequent (from Java 8 onwards). Multiple entries in the same bucket are connected through this list or tree.
Resizing
HashMap dynamically resizes when the range of factors exceeds the product of the load factor and initial capacity. It doubles the array length and rehashes all of the entries, redistributing them to new buckets.
Treeification
When the number of elements in a single bucket exceeds a threshold (typically 8), the linked list inside the bucket is converted into a balanced binary tree. This improves performance during lookups by reducing the time complexity for heavily populated buckets.
Real-time Applications of HashMap
HashMap is widely used in various real-world applications due to its efficient data retrieval and management. Below are some common use cases of HashMap in real-time scenarios:
Caching: It is the storage of frequently accessed information for quick retrieval.
Counting Frequencies: Keeping a log of occurrences of elements, along with phrase counts in a document.
Caching: Storing frequently accessed data for quick retrieval.
Database Indexing: Managing key-based indexing for faster database searches.
Session Management: Mapping session IDs to user data in web applications.
Configuration Management: Storing and retrieving configuration settings for software systems.
Router Tables: Storing IP addresses and routing information in network routers.
Shopping Cart: Mapping product IDs to quantities in e-commerce platforms.
Building Dictionaries: Managing word-to-definition mappings in language processing.
File System Management: Storing file metadata for faster access and organisation.
Storing User Preferences: Saving user settings in software applications for quick access.
Implements the Map interface, storing key-value pairs.
Implements the Set interface, storing only unique values.
Data Structure
Stores data in key-value pairs. Each key is unique, and a value is associated with each key.
Stores only unique elements, with no duplicate values allowed.
Null Values
Allows one null key and multiple null values.
Allows only one null value.
Usage
Suitable for key-value pair scenarios, where quick lookup of keys is needed.
Suitable when only a unique collection of values is needed.
Performance
Average time complexity for basic operations like insertion, deletion, and access is O(1).
Similar performance with O(1) for basic operations, but only works with values.
Internal Structure
Uses hashing to store elements as key-value pairs.
Uses hashing to store unique values.
Duplicates
Keys must be unique, but duplicate values are allowed.
Does not allow duplicate elements.
Primary Purpose
Used when you need to associate keys with values.
Used when you need to store a collection of unique values.
Methods
Provides methods like put(), get(), remove().
Provides methods like add(), remove(), contains().
Null Handling
Can store one null key and multiple null values.
Can store only one null value.
Methods of HashMap Class
Method
Description
Parameters
Return Type
clear()
Removes all key-value pairs from the map.
None
void
clone()
Returns a shallow copy of the HashMap.
None
Object
compute()
Computes a new mapping for the specified key using the provided function.
key, BiFunction
V (value)
computeIfAbsent()
If the specified key is not already associated with a value, computes and associates a value.
key, Function
V (value)
computeIfPresent()
If the key is already associated with a value, compute a new value for the key.
key, BiFunction
V (value)
containsKey()
Returns true if the map contains a mapping for the specified key.
key
boolean
containsValue()
Returns true if the map contains one or more keys mapped to the specified value.
value
boolean
entrySet()
Returns a Set view of the key-value mappings in the map.
None
Set<Map.Entry<K,V>>
forEach()
Performs the given action for each entry in the map.
BiConsumer
void
get()
Returns the value associated with the specified key, or null if the key is not present.
key
V (value)
getOrDefault()
Returns the value for the specified key, or the default value if the key is not found.
key, defaultValue
V (value)
isEmpty()
Returns true if the map contains no key-value pairs.
None
boolean
keySet()
Returns a Set view of the keys contained in the map.
None
Set<K>
merge()
Merges the value associated with the key using the provided function.
key, value, BiFunction
V (value)
put()
Associates the specified value with the specified key in the map.
key, value
V (value)
putAll()
Copies all mappings from the specified map to this map.
Map<? extends K,? extends V>
void
putIfAbsent()
Associates the value with the specified key if the key is not already associated with a value.
key, value
V (value)
remove()
Removes the mapping for the specified key, or the entry if both key and value match.
key, value (optional)
V (value) or boolean
replace()
Replaces the entry for the specified key only if it is currently mapped to some value.
key, value or key, oldValue, newValue
V (value) or boolean
replaceAll()
Replaces each entry’s value with the result of the given function.
BiFunction
void
size()
Returns the number of key-value pairs in the map.
None
int
values()
Returns a Collection view of the values contained in the map.
None
Collection<V>
Conclusion
In conclusion, HashMap is a notably efficient and versatile data structure in Java, widely used for its speedy access to key-value pairs. It gives numerous strategies for adding, retrieving, and manipulating data whilst permitting flexibility with null keys and values. Despite its remarkable overall performance, we have to understand how hashing and collisions work to get critical information on real-time applications.
With a decent knowledge of the HashMap class, consisting of its constructors, methods, and operations, you can definitely implement it in your projects and organisation’s work. You can confidently complete fast lookups, and make efficient records and vital controls of the functions where the HashMap is used. It is one of the most effective tools in the Java Collections Framework and remains a preferred choice for developers. Want to master Java? Check out
FAQs
What is a HashMap in Java?
A HashMap stores data in key-value pairs, providing fast access through unique keys.
Can HashMap have null keys?
Yes, HashMap allows one null key and multiple null values.
What is the default load factor in HashMap?
The default load factor is 0.75, which balances performance and memory usage.
Is HashMap thread-safe?
No, HashMap is not synchronised. For thread-safe operations, use ConcurrentHashMap
What happens when two keys have the same hash code?
This results in a collision, and the HashMap handles it using linked lists or trees.
Can HashMap store duplicate values?
Yes, it can store duplicate values, but keys must be unique.
How to iterate over a HashMap?
You can iterate using entrySet(), keySet(), or forEach() methods
Hero Vired is a leading LearnTech company dedicated to offering cutting-edge programs in collaboration with top-tier global institutions. As part of the esteemed Hero Group, we are committed to revolutionizing the skill development landscape in India. Our programs, delivered by industry experts, are designed to empower professionals and students with the skills they need to thrive in today’s competitive job market.