HashMap in Java
HashMap in Java is a part of the Java Collections Framework, implementing the Map interface. It stores data in key-value pairs, allowing efficient data retrieval, insertion, and deletion based on the key. Keys are unique within a HashMap, ensuring that each key maps to exactly one value. The HashMap is unsynchronized and permits null values as well as one null key. It uses a hashing technique to compute an index at which data is stored and retrieved, which allows it to perform most operations—such as get() and put()—in constant time under typical conditions. HashMap is not ordered; it does not maintain the order of its elements, whether by insertion time or by any sorting order.
Functions of HashMap in Java:
-
Put Elements:
Allows the insertion of key-value pairs into the map. If the map previously contained a mapping for a key, the old value is replaced.
-
Get Elements:
Enables retrieval of values based on their keys. Returns null if the key is not found.
-
Remove Elements:
Deletes a key-value pair from the map using the key.
-
Check Key Existence:
Verifies whether a specific key exists in the map.
-
Check Value Existence:
Checks whether a particular value is present in the map at least once.
-
Size of the Map:
Returns the number of key-value pairs present in the map.
-
Clear the Map:
Removes all the key-value pairs from the map, effectively clearing it.
-
Collection Views:
Provides views of the keys, values, or key-value mappings (entries) as collections. These views are backed by the map, meaning changes in the map are reflected in the views.
-
Iterate over Keys or Values:
Facilitates iteration over keys or values using these views, which can be crucial for certain applications where data needs to be processed element by element.
-
Load Factors and Rehashing:
Automatically increases the size of the HashMap when the number of elements in the map exceeds a certain threshold of the map’s capacity, thus maintaining an efficient mapping performance.
-
Compute Methods:
Java 8 introduced methods like computeIfAbsent and computeIfPresent, which allow for more complex atomic operations based on keys.
-
Merge and Replace Functionalities:
Allows merging of values based on keys and replacement of values under certain conditions.
Example of HashMap in Java:
This example demonstrates several basic operations like adding items, checking for existence, and iterating over entries.
import java.util.HashMap;
import java.util.Map;
public class HashMapExample {
public static void main(String[] args) {
// Create a HashMap
HashMap<String, Integer> map = new HashMap<>();
// Adding elements to the HashMap
map.put(“Alice”, 30);
map.put(“Bob”, 25);
map.put(“Charlie”, 35);
// Displaying the size of the map
System.out.println(“Size of map is: ” + map.size());
// Checking if a key exists
if (map.containsKey(“Alice”)) {
System.out.println(“Alice is in the map and her age is ” + map.get(“Alice”));
}
// Iterating over map entries
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ” is ” + entry.getValue() + ” years old.”);
}
// Remove an entry
map.remove(“Charlie”);
System.out.println(“After removing Charlie, size of map is: ” + map.size());
// Replace an entry
map.replace(“Bob”, 26);
System.out.println(“Bob’s new age is: ” + map.get(“Bob”));
// Checking if the map contains a value
if (map.containsValue(26)) {
System.out.println(“There is at least one person who is 26 years old.”);
}
// Clearing all entries
map.clear();
System.out.println(“Map is empty, size: ” + map.size());
}
}
This simple program creates a HashMap, adds some elements to it, and then performs various operations such as checking the existence of a key, iterating over all elements, modifying and removing elements, and finally clearing the map.
Hashtable in Java
Hashtable in Java is a part of the Java Collections Framework but predates it, coming from the original Java 1.0. It implements a hash table, which maps keys to values. Any non-null object can be used as a key or value. Being synchronized, Hashtable ensures that only one thread can access the hash table at a time, making it thread-safe but potentially less efficient in scenarios where high concurrency is desired. It does not allow null keys or values, differing from HashMap, which is part of the newer Collections framework and permits nulls but is unsynchronized. Hashtable is generally considered legacy code; thus, developers are encouraged to use ConcurrentHashMap or HashMap depending on their specific thread-safety requirements.
Functions of Hashtable in Java:
-
Storing Key-Value Pairs:
Stores data in key-value pair format, where each key maps to exactly one value.
-
Data Retrieval:
Allows efficient retrieval of values by specifying their corresponding keys.
- Synchronization:
Ensures that the table is thread-safe by synchronizing each method, meaning only one thread can access the hash table at a time.
-
Handling Collisions:
Implements collision handling using chaining, meaning multiple entries can exist at the same hash value but are stored in a linked list format.
-
Enumeration Support:
Provides methods to retrieve enumeration of keys, values, or key-value entries.
- Cloneable:
Supports cloning where you can create a shallow copy of the hashtable.
-
Null Prohibition:
Does not allow null keys or values, which helps in avoiding runtime exceptions due to null values.
- Serializable:
Implements the Serializable interface, allowing hashtable objects to be serialized.
-
Legacy Integration:
Maintains compatibility with older versions of Java, ensuring that applications written for earlier versions can still function.
Example of Hashtable in Java:
This example demonstrates how to create a Hashtable, add key-value pairs to it, retrieve a value, check for a key, and iterate over the keys and values of the hashtable.
import java.util.*;
public class HashtableExample {
public static void main(String[] args) {
// Create a Hashtable
Hashtable<String, Integer> numbers = new Hashtable<>();
// Adding key-value pairs to the Hashtable
numbers.put(“One”, 1);
numbers.put(“Two”, 2);
numbers.put(“Three”, 3);
// Retrieve a value
Integer n = numbers.get(“Two”);
if (n != null) {
System.out.println(“Value for key ‘Two’: ” + n);
}
// Check if a key exists in the Hashtable
if (numbers.containsKey(“Three”)) {
System.out.println(“Hashtable contains key ‘Three'”);
}
// Iterate over keys
System.out.println(“Keys in Hashtable:”);
for (String key : numbers.keySet()) {
System.out.println(key);
}
// Iterate over values
System.out.println(“Values in Hashtable:”);
for (Integer value : numbers.values()) {
System.out.println(value);
}
// Iterate over key-value pairs
System.out.println(“Entries in Hashtable:”);
for (Map.Entry<String, Integer> entry : numbers.entrySet()) {
System.out.println(“Key: ” + entry.getKey() + “, Value: ” + entry.getValue());
}
}
}
In this example:
- Hashtable named numbers is created to store String keys and Integer
- Three key-value pairs are added to the hashtable.
- The value associated with the key “Two” is retrieved and printed.
- The presence of the key “Three” is checked and printed if it exists.
- The program iterates over and prints all keys, all values, and all key-value pairs from the hashtable, demonstrating various ways to access the data stored in a Hashtable.
Key differences between HashMap and Hashtable in Java
Aspect | HashMap | Hashtable |
Synchronization | Not synchronized | Synchronized |
Thread-safe | No | Yes |
Null keys and values | Allows one null key, multiple null values | No null keys or values allowed |
Performance | Faster due to non-synchronization | Slower due to synchronization |
Iterators | Fail-fast | Fail-fast |
Legacy | Not a legacy | Legacy class |
Superclass | AbstractMap | Dictionary |
Method Specific | Provides putIfAbsent, forEach, replace | Lacks modern Map methods |
Concurrency control | Can be handled by ConcurrentHashMap | None needed (inherent) |
Ideal usage | Non-threaded applications | Threaded applications |
Initial capacity handling | Initial capacity, load factor are configurable | Same, but rehashes more conservatively |
Output ordering | No order guarantee | No order guarantee |
Fail-fast behavior | Iterators are fail-fast | Iterators are fail-fast |
Introduced version | Java 1.2 | Java 1.0 |
Subclass | Can accept subclasses of Map | Extends Dictionary, fewer subtypes |
Key Similarities between HashMap and Hashtable in Java
- Purpose:
Both are used to store data in key-value pairs, making it easy to access data via a key.
-
Data Structure:
They both implement the Map interface (although Hashtable indirectly as a subclass of Dictionary) and use a hash table as their underlying data structure.
-
API Methods:
They provide similar basic operations such as get, put, and remove for managing key-value pairs.
-
Key-based access:
The access to values is based on keys, and both require keys to implement the hashCode() and equals() methods to correctly locate values in the map.
-
Capacity and Load factor:
Both HashMap and Hashtable handle internal capacity and a load factor which determines when the map needs to be resized. Although the details and defaults might differ, the concept of load factor influencing performance is common.
- Iterators:
Iterators obtained from both HashMap and Hashtable are fail-fast, meaning they will throw a ConcurrentModificationException if the map is structurally modified after the iterator is created, except through the iterator’s own remove method.
-
Non-ordered:
Neither HashMap nor Hashtable guarantee any specific order of entries; the order can change when items are inserted or removed.
-
Hash-based indexing:
They both use the object’s hash code to determine where keys are stored internally.