The IdentityHashMap class in Java is a Map implementation that uses reference equality (==) instead of object equality (equals) for comparing keys and values. It is part of the java.util package and is intended for specialized use cases where identity-based comparison is required instead of logical equality.
1. Overview of IdentityHashMap
- Definition:
IdentityHashMap<K, V>is a hash table-based Map implementation where keys and values are compared using reference equality (==) rather than theequals()method. - Key Characteristics:
- Uses
==operator for key comparison instead ofequals(). - Does not allow null keys in some operations, but allows null values.
- Iteration order is not predictable; it is generally unsorted.
- More memory efficient and faster than
HashMapfor identity-based key mapping. - Not synchronized; it is not thread-safe.
- Uses
- Hierarchy:
java.lang.Object
-> java.util.AbstractMap<K, V>
-> java.util.IdentityHashMap<K, V>
- Primary Use Case: Situations where object identity matters rather than logical equality, e.g., maintaining a mapping for interned objects, proxies, or wrapper objects.
2. Internal Working
IdentityHashMapuses a hash table internally, but the hash code is computed fromSystem.identityHashCode(key)rather than thehashCode()method.- Keys are compared using
==, notequals(). - This allows multiple objects that are logically equal but different instances to exist as separate keys.
String a = new String("key");
String b = new String("key");
Map<String, String> hashMap = new HashMap<>();
hashMap.put(a, "value1");
hashMap.put(b, "value2");
System.out.println(hashMap); // {key=value2}, keys considered equal
Map<String, String> identityMap = new IdentityHashMap<>();
identityMap.put(a, "value1");
identityMap.put(b, "value2");
System.out.println(identityMap); // {key=value1, key=value2}, keys are different by identity
3. Creating an IdentityHashMap
3.1 Default Constructor
IdentityHashMap<String, String> map = new IdentityHashMap<>();
map.put("A", "Apple");
map.put("B", "Banana");
System.out.println(map); // {A=Apple, B=Banana}
3.2 Initial Capacity Constructor
IdentityHashMap<String, String> map = new IdentityHashMap<>(10);
- Sets the initial capacity of the internal hash table.
- Load factor is fixed internally (cannot be set externally).
3.3 Copy Constructor
Map<String, String> original = new HashMap<>();
original.put("A", "Apple");
IdentityHashMap<String, String> identityMap = new IdentityHashMap<>(original);
System.out.println(identityMap); // {A=Apple}
4. Adding and Removing Elements
IdentityHashMap supports standard Map operations:
IdentityHashMap<String, String> map = new IdentityHashMap<>();
String key1 = new String("key");
String key2 = new String("key");
map.put(key1, "Value1");
map.put(key2, "Value2");
System.out.println(map.get(key1)); // Value1
System.out.println(map.get(key2)); // Value2
System.out.println(map.size()); // 2, keys are different by identity
map.remove(key1);
System.out.println(map); // {key=Value2}
5. Iterating Over IdentityHashMap
Iteration is similar to other maps, but remember iteration order is unpredictable:
IdentityHashMap<String, String> map = new IdentityHashMap<>();
map.put("A", "Apple");
map.put("B", "Banana");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
for (String key : map.keySet()) {
System.out.println(key + " : " + map.get(key));
}
6. Key Points to Remember
- Identity Comparison: Keys are compared using
==, notequals(). - Hash Code: Uses
System.identityHashCode()instead ofhashCode(). - Duplicate Logical Keys: Multiple instances with the same logical value can coexist as keys.
- Null Keys and Values: Allows
nullas key or value. - Not Thread-Safe: Use
Collections.synchronizedMap()for concurrent access. - Iteration Order: Unpredictable; do not rely on insertion order.
7. Use Cases of IdentityHashMap
- Tracking Object References: Useful when object identity matters, e.g., memoization of object references.
IdentityHashMap<Object, String> map = new IdentityHashMap<>(); Object obj1 = new Object(); Object obj2 = new Object(); map.put(obj1, "Object1"); map.put(obj2, "Object2");
- Proxies or Interned Objects: Manage unique object instances rather than logical equality.
- Graph Algorithms: Track visited nodes in graphs by object reference, not by content equality.
- Serialization or Cloning: Maintain a mapping of original objects to copies during deep cloning.
8. Comparison with Other Maps
| Feature | HashMap | IdentityHashMap | WeakHashMap |
|---|---|---|---|
| Key Comparison | equals() | == | equals() (weak reference) |
| Hash Code | hashCode() | System.identityHashCode() | hashCode() |
| Null Key Allowed | Yes | Yes | Yes |
| Automatic Cleanup | No | No | Yes (GC removes keys) |
| Thread Safety | No | No | No |
| Use Case | General purpose map | Identity-based mapping | Memory-sensitive cache |
9. Summary
IdentityHashMap is a specialized Map in Java:
- Uses reference equality (
==) for keys instead ofequals(). - Uses
System.identityHashCode()to compute hash codes. - Allows multiple logically equal objects as separate keys.
- Not synchronized and iteration order is unpredictable.
- Ideal for identity-based caches, tracking object references, or graph algorithms.
