HashMap
Time Complexity
Data Structures
Java Collections
Algorithm Efficiency

HashMap get/put complexity

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

HashMaps are a popular data structure in many programming languages, known for their efficiency in key-value pair storage and retrieval. Understanding the complexity of get and put operations in HashMaps is crucial for optimizing performance in applications that require frequent data access. Let's delve into the technical details of these operations and their complexities.

Overview of HashMap

A HashMap is a data structure that implements an associative array abstraction, where keys are mapped to values. Internally, a HashMap uses an array and a hash function to compute an index for each key-value pair, which determines where the pair is stored within the array. The hash function transforms the key into a hash code, which is then used to locate the index.

Main Operations: get and put

  • Get Operation: The get(key) method retrieves the value associated with the specified key.
  • Put Operation: The put(key, value) method inserts a key-value pair into the HashMap. If the key already exists, the associated value is updated.

Complexity Analysis

The time complexity of both get and put operations depends on several factors, such as how well the hash function distributes keys and the presence of hash collisions.

Average Case Complexity

For both operations, under average conditions, the time complexity is O(1)O(1) (constant time). This efficiency comes from a well-dispersed hash function, which spreads keys evenly across the array, minimizing collisions.

  1. Get Operation: In an average scenario, retrieving a value requires computing the hash of the key and directly accessing the indexed position in the array, resulting in O(1)O(1) complexity.
  2. Put Operation: Similarly, inserting a key-value pair involves calculating the hash and placing the value at the corresponding index, also resulting in O(1)O(1) complexity.

Worst Case Complexity

In the worst case, the time complexity for both get and put operations becomes O(n)O(n), where nn is the number of entries in the HashMap. This scenario occurs when all keys collide, meaning they hash to the same index, converting the HashMap's array into a linked list — or worse, a binary tree in some implementations.

  • Handling Collisions: To handle collisions, HashMaps typically use chaining (where each array bucket contains a linked list or another data structure to accommodate multiple key-value pairs).

Load Factor and Resizing

The load factor of a HashMap is a measure of how full the HashMap is allowed to get before it needs to resize its internal data structure. The default load factor is 0.75 in most implementations (e.g., Java's HashMap). When the load factor threshold is exceeded, the HashMap undergoes resizing (typically doubling the capacity) and rehashing, which involves redistributing all existing key-value pairs—a process with O(n)O(n) complexity.

Technical Considerations

  1. Choosing a Good Hash Function: A good hash function evenly distributes keys to minimize collisions and maintain constant time complexity.
  2. Capacity Planning: Selecting an appropriate initial capacity avoids excessive resizing operations.
  3. Handling High Collision Rate: Modern implementations, such as Java's HashMap, convert buckets with high collisions into balanced trees, improving search time from O(n)O(n) to O(logn)O(\log n).

Code Example

Here's a simple example in Java highlighting the use of get and put:

java
1import java.util.HashMap;
2
3public class HashMapExample {
4    public static void main(String[] args) {
5        HashMap<String, Integer> map = new HashMap<>();
6
7        // Put Operations
8        map.put("apple", 1);
9        map.put("banana", 2);
10        map.put("cherry", 3);
11
12        // Get Operations
13        System.out.println("Value for key 'apple': " + map.get("apple")); // Outputs 1
14        System.out.println("Value for key 'banana': " + map.get("banana")); // Outputs 2
15    }
16}

In this example, both put and get operations exhibit an average complexity of O(1)O(1).

Summary Table

Below is a table summarizing key complexities and considerations:

OperationAverage Time ComplexityWorst Case Time ComplexityNotes
get(key)O(1)O(1)O(n)O(n)Dependent on hash collisions
put(key, value)O(1)O(1)O(n)O(n)Resize operation has O(n)O(n) complexity
ResizingO(n)O(n)O(n)O(n)Triggered by load factor threshold

Additional Considerations

  • HashMap VS TreeMap: Unlike HashMaps, TreeMaps structure data in a sorted order using a tree, providing O(logn)O(\log n) complexity for all operations.
  • Thread Safety: HashMap is not thread-safe, meaning concurrent modifications can lead to inconsistent states. For thread-safe operations, consider using classes like ConcurrentHashMap.

By understanding the complexities and nuances of HashMap operations, developers can make informed decisions about when to use HashMaps and how to optimize their performance in different scenarios.


Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.