Learnitweb

Java IdentityHashMap

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 the equals() method.
  • Key Characteristics:
    1. Uses == operator for key comparison instead of equals().
    2. Does not allow null keys in some operations, but allows null values.
    3. Iteration order is not predictable; it is generally unsorted.
    4. More memory efficient and faster than HashMap for identity-based key mapping.
    5. Not synchronized; it is not thread-safe.
  • 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

  • IdentityHashMap uses a hash table internally, but the hash code is computed from System.identityHashCode(key) rather than the hashCode() method.
  • Keys are compared using ==, not equals().
  • 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

  1. Identity Comparison: Keys are compared using ==, not equals().
  2. Hash Code: Uses System.identityHashCode() instead of hashCode().
  3. Duplicate Logical Keys: Multiple instances with the same logical value can coexist as keys.
  4. Null Keys and Values: Allows null as key or value.
  5. Not Thread-Safe: Use Collections.synchronizedMap() for concurrent access.
  6. Iteration Order: Unpredictable; do not rely on insertion order.

7. Use Cases of IdentityHashMap

  1. 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");
  1. Proxies or Interned Objects: Manage unique object instances rather than logical equality.
  2. Graph Algorithms: Track visited nodes in graphs by object reference, not by content equality.
  3. Serialization or Cloning: Maintain a mapping of original objects to copies during deep cloning.

8. Comparison with Other Maps

FeatureHashMapIdentityHashMapWeakHashMap
Key Comparisonequals()==equals() (weak reference)
Hash CodehashCode()System.identityHashCode()hashCode()
Null Key AllowedYesYesYes
Automatic CleanupNoNoYes (GC removes keys)
Thread SafetyNoNoNo
Use CaseGeneral purpose mapIdentity-based mappingMemory-sensitive cache

9. Summary

IdentityHashMap is a specialized Map in Java:

  • Uses reference equality (==) for keys instead of equals().
  • 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.