HashMap
is a part of the Java Collections Framework and is used to store data in key-value pairs. It is implemented as a hash table, which means it uses a hash function to compute an index into an array of buckets or slots, from which the desired value can be found.
Key Concepts of HashMap
Implementation
- Data Structure:
- Explanation: Internally,
HashMap
uses an array ofNode<K, V>
objects, where eachNode
represents a key-value pair. EachNode
contains four fields: the key, the value, the hash code, and a reference to the nextNode
(for handling collisions). - Example:
java
static class Node<K, V> {
final int hash;
final K key;
V value;
Node<K, V> next;
// constructor and other methods
}
- Hashing:
- Explanation: When you insert a key-value pair into a
HashMap
, the hash code of the key is computed using thehashCode()
method. This hash code is then used to determine the index in the array where theNode
should be placed. - Example:
java
int hash = key.hashCode();
int index = (n - 1) & hash; // n is the length of the array
- Collision Handling:
- Explanation: Collisions occur when two keys have the same hash code and thus map to the same bucket.
HashMap
handles collisions using a linked list or a binary tree (in case of high collisions), where eachNode
in the list points to the nextNode
in the same bucket. - Example:
If two keys have the same index, they are stored in a linked list at that index:
java
Node<K, V> newNode = new Node<>(hash, key, value, null);
if (table[index] == null) {
table[index] = newNode;
} else {
Node<K, V> current = table[index];
while (current.next != null) {
current = current.next;
}
current.next = newNode;
}
- Load Factor and Resizing:
- Explanation:
HashMap
has a load factor (default is 0.75), which determines when the array needs to be resized. When the number of entries exceeds the product of the load factor and the current capacity, theHashMap
doubles the size of the array and rehashes all the entries to new buckets. - Example:
java
if (size > threshold) {
resize();
}
- Rehashing:
- Explanation: Rehashing involves recalculating the index for each key in the
HashMap
when the array is resized. This is necessary because the position of each key-value pair might change with the new array size. - Example:
During resizing, all entries are redistributed based on their new hash indexes in the larger array.
- Treeify:
- Explanation: If a single bucket contains too many entries (by default, more than 8), the
HashMap
converts the linked list of that bucket into a balanced tree (usually a Red-Black tree) to improve performance from O(n) to O(log n). - Example:
java
if (binCount >= TREEIFY_THRESHOLD) {
treeifyBin(tab, hash);
}
Example of Basic HashMap
Usage
Here’s a simple example of using a HashMap
:
import java.util.HashMap; public class HashMapExample {
public static void main(String args) {
HashMap<String, Integer> map = new HashMap<>();
// Inserting key-value pairs
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Orange", 3);
// Retrieving value by key
int value = map.get("Apple");
System.out.println("Value for Apple: " + value);
// Iterating over the HashMap
for (String key : map.keySet()) {
System.out.println("Key: " + key + ", Value: " + map.get(key));
}
}
}
Explanation:
- The put
method inserts key-value pairs into the HashMap
, calculating the appropriate bucket using the hash of the key.
- The get
method retrieves the value associated with a given key by finding the correct bucket and searching for the key within that bucket.