Open In App

IdentityHashMap class in Java

Improve
Improve
Like Article
Like
Save
Share
Report

The IdentityHashMap implements Map interface using Hashtable, using reference-equality in place of object-equality when comparing keys (and values). This class is not a general-purpose Map implementation. While this class implements the Map interface, it intentionally violates Map’s general contract, which mandates the use of the equals() method when comparing objects. This class is used when the user requires the objects to be compared via reference. It belongs to java.util package.

Features of IdentityHashMap

  • It follows reference equality, instead of using the equals() method it uses the == operator.
  • It is not synchronized and must be synchronized externally.
  • Iterators are fail-fast, throw ConcurrentModificationException in an attempt to modify while iterating.
  • This class provides constant-time performance for the basic operations (get and put), assuming the system identity hash function (System.identityHashCode(Object)) disperses elements properly among the buckets. IdentityHashMap doesn’t use hashCode() method instead it uses System.identityHashCode() method. This is a significant difference because now you can use mutable objects as key in Map whose hash code is likely to change when the mapping is stored inside IdentityHashMap.

Declaration:

public class IdentityHashMap<K,?V> extends AbstractMap<K,?V> implements Map<K,?V>, Serializable, Cloneable 
 

Here, K is the key Object type and V is the value Object type.

In Java, IdentityHashMap is a class that implements the Map interface. It is similar to the HashMap class, with the main difference being that IdentityHashMap uses reference equality instead of object equality when comparing keys.

While HashMap uses the equals() method to compare the keys, IdentityHashMap uses the == operator to compare the keys. This means that in an IdentityHashMap, two keys are considered equal if and only if they are the same object, rather than being equal in terms of their contents.

Here is an example of how you might use an IdentityHashMap in Java:

Java




import java.util.IdentityHashMap;
  
public class Example {
    public static void main(String[] args) {
        IdentityHashMap<String, Integer> identityHashMap = new IdentityHashMap<>();
        identityHashMap.put("A", 1);
        identityHashMap.put(new String("A"), 2);
        System.out.println(identityHashMap.size()); // 2
        System.out.println(identityHashMap.get("A")); // 1
    }
}


output;

1

The IdentityHashMap class in Java is a hash table-based implementation of the Map interface that uses reference-equality in place of object-equality when comparing keys (and values).

Advantages of using IdentityHashMap over HashMap:

  1. Faster lookups: Since IdentityHashMap uses reference-equality for comparison, it is faster for lookups compared to HashMap which uses object-equality.
  2. Useful for comparing object instances: IdentityHashMap is useful in situations where you want to compare object instances rather than object values.

Disadvantages of using IdentityHashMap:

  1. Uses more memory: IdentityHashMap uses more memory compared to HashMap as it needs to store the reference to the object.
  2. Not suitable for all use cases: IdentityHashMap is not suitable for all use cases and should be used with caution as it can lead to unexpected behavior in certain situations.

 

The Hierarchy of IdentityHashMap

IdentityHashMap in Java

It implements Serializable, Cloneable, Map<K,? V> interfaces and extends AbstractMap<K, V> class.

Example:

Java




// Java code to demonstrate IdentityHashMap 
  
import java.util.Map;
import java.util.HashMap;
import java.util.IdentityHashMap;
  
public class IdentityHashMapExample 
{
    public static void main(String[] args) 
    {
        // creating an instance of IdentityHashMap
        Map<String, String> ihm = new IdentityHashMap<>();
  
        // Putting key and value pair
        // in a IdentityHashMap Object
        ihm.put("ihmkey","ihmvalue"); 
        ihm.put(new String("ihmkey"),"ihmvalue1"); 
          
        // ihm.size() will print 2 since it 
        // compares the objects by reference
        System.out.println("Size of IdentityHashMap--"+ihm.size());
          
    }
}


Output

Size of IdentityHashMap--2

Constructors of IdentityHashMap

We can create an instance of IdentityHashMap in two ways:

IdentityHashMap<K, V> ihm = new IdentityHashMap<K, V>();
            (or)
Map<K, V> hm = new IdentityHashMap<K, V>();

1. IdentityHashMap(): Constructs a new, empty identity hash map with a default expected maximum size. 

IdentityHashMap<K, V> ihm = new IdentityHashMap<K, V>();

2. IdentityHashMap(int expectedMaxSize): Constructs a new, empty map with the specified expected maximum size. 

IdentityHashMap<K, V> ihm = new IdentityHashMap(int expectedMaxSize);

3. IdentityHashMap(Map m): Constructs a new identity hash map containing the key-value mappings in the specified map.

IdentityHashMap<K, V> ihm = new IdentityHashMap(Map m);

Basic Operations on IdentityHashMap

1. Adding Elements

To insert or add mapping into an IdentityHashMap, we have put() and putAll() methods. put() can insert a specific key and the value it is mapping, into a particular map. If an existing key is passed then the previous value gets replaced by the new value. putAll() copies all of the elements i.e., the mappings, from one map into another. 

Java




// Java code to illustrate
// adding elements to IdentityHashMap
import java.util.*;
  
public class AddingElementsToIdentityHashMap {
    
    public static void main(String[] args)
    {
        // Creating an empty IdentityHashMap
        Map<Integer, String> identity_hash
            = new IdentityHashMap<Integer, String>();
  
        // Mapping string values to int keys
        // using put() method
        identity_hash.put(10, "Geeks");
        identity_hash.put(15, "4");
        identity_hash.put(20, "Geeks");
        identity_hash.put(25, "Welcomes");
        identity_hash.put(30, "You");
  
        // Displaying the IdentityHashMap
        System.out.println("Initial Mappings are: "
                           + identity_hash);
  
        // Inserting existing key along with new value
          // previous value gets returned and stored in
          // returned_value
        String returned_value
            = (String)identity_hash.put(20, "All");
  
        // Verifying the returned value
        System.out.println("Returned value is: "
                           + returned_value);
  
        // Displaying the new map
        System.out.println("New map is: " + identity_hash);
  
        // Creating a new Identityhash map and copying
        Map<Integer, String> new_Identityhash_map
            = new IdentityHashMap<Integer, String>();
        new_Identityhash_map.putAll(identity_hash);
  
        // Displaying the final IdentityHashMap
        System.out.println("The new map: "
                           + new_Identityhash_map);
    }
}


Output

Initial Mappings are: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=Geeks}
Returned value is: Geeks
New map is: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=All}
The new map: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=All}

2. Removing Elements
To remove mappings, we use remove(), an inbuilt method of IdentityHashMap class, and is used to remove the mapping of any particular key from the map.

Java




// Java code to illustrate removing
// elements from IdentityHashMap
  
import java.util.*; 
  
public class RemovingMappingsFromIdentityHashMap { 
    public static void main(String[] args) 
    
  
        // Creating an empty IdentityHashMap 
        Map<Integer, String> Identity_hash = new
                    IdentityHashMap<Integer, String>(); 
      
        // Mapping string values to int keys 
        Identity_hash.put(10, "Geeks"); 
        Identity_hash.put(15, "4"); 
        Identity_hash.put(20, "Geeks"); 
        Identity_hash.put(25, "Welcomes"); 
        Identity_hash.put(30, "You"); 
  
        // Displaying the IdentityHashMap 
        System.out.println("Initial Mappings are: "
                                        Identity_hash); 
  
        // Removing the existing key mapping 
        String returned_value = 
                        (String)Identity_hash.remove(20); 
  
        // Verifying the returned value 
        System.out.println("Returned value is: "
                                    returned_value); 
  
        // Displaying the new map 
        System.out.println("New map is: " + Identity_hash); 
    


Output

Initial Mappings are: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=Geeks}
Returned value is: Geeks
New map is: {30=You, 10=Geeks, 15=4, 25=Welcomes}

3. Accessing the Elements

We can access the elements of an IdentityHashMap using the get() method, the example of this is given below.

Java




// Java code to illustrate the accessing
// elements from IdentityHashMap
  
import java.util.*;
  
public class AccessingElementsFromIdentityHashMap {
  
    public static void main(String[] args)
    {
  
        // Creating an empty IdentityHashMap
        Map<Integer, String> identity_hash
            = new IdentityHashMap<Integer, String>();
  
        // Mapping string values to int keys
        identity_hash.put(10, "Geeks");
        identity_hash.put(15, "4");
        identity_hash.put(20, "Geeks");
        identity_hash.put(25, "Welcomes");
        identity_hash.put(30, "You");
  
        // Displaying the IdentityHashMap
        System.out.println("Initial Mappings are: "
                           + identity_hash);
  
        // Getting the value of 25
        System.out.println("The Value is: "
                           + identity_hash.get(25));
  
        // Getting the value of 10
        System.out.println("The Value is: "
                           + identity_hash.get(10));
        
          // Using keySet() to get the set view of keys 
        System.out.println("The set is: " + identity_hash.keySet()); 
            
          // Using entrySet() to get the set view 
        System.out.println("The set is: "
                                identity_hash.entrySet()); 
    }
}


Output

Initial Mappings are: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=Geeks}
The Value is: Welcomes
The Value is: Geeks
The set is: [30, 10, 15, 25, 20]
The set is: [30=You, 10=Geeks, 15=4, 25=Welcomes, 20=Geeks]

4. Traversing
We can use the Iterator interface to traverse over any structure of the Collection Framework. Since Iterators work with one type of data we use Entry< ? , ? > to resolve the two separate types into a compatible format. Then using the next() method we print the elements of the IdentityHashMap.

Java




// Java code to illustrate the 
// iterating over IdentityHashmap
  
import java.util.*;
  
public class IteratingIdentityHashMap {
  
    public static void main(String[] args)
    {
  
        // Creating an empty IdentityHashMap
        IdentityHashMap<Integer, String> identity_hash
            = new IdentityHashMap<Integer, String>();
  
        // Mapping string values to int keys
        identity_hash.put(10, "Geeks");
        identity_hash.put(15, "4");
        identity_hash.put(20, "Geeks");
        identity_hash.put(25, "Welcomes");
        identity_hash.put(30, "You");
  
        // Displaying the IdentityHashMap
        System.out.println("Initial Mappings are: "
                           + identity_hash);
  
        // Create an Iterator over the
        // IdentityHashMap
        Iterator<IdentityHashMap.Entry<Integer, String> >
            itr = identity_hash.entrySet().iterator();
  
        // The hasNext() method is used to check if there is
        // a next element The next() method is used to
        // retrieve the next element
        while (itr.hasNext()) {
            IdentityHashMap.Entry<Integer, String> entry
                = itr.next();
            System.out.println("Key = " + entry.getKey()
                               + ", Value = "
                               + entry.getValue());
        }
    }
}


Output

Initial Mappings are: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=Geeks}
Key = 30, Value = You
Key = 10, Value = Geeks
Key = 15, Value = 4
Key = 25, Value = Welcomes
Key = 20, Value = Geeks

Synchronized IdentityHashMap

If multiple threads access an identity hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be “wrapped” using the Collections.synchronizedMap method. This is best done at creation time, to prevent accidental unsynchronized access to the map. 

Map m = Collections.synchronizedMap(new IdentityHashMap(…));

Methods of IdentityHashMap

  • K – The type of the keys in the map.
  • V – The type of values mapped in the map.

METHOD

DESCRIPTION

clear() Removes all of the mappings from this map.
clone() Returns a shallow copy of this identity hash map: the keys and values themselves are not cloned.
containsKey?(Object key) Tests whether the specified object reference is a key in this identity hash map.
containsValue?(Object value) Tests whether the specified object reference is a value in this identity hash map.
entrySet() Returns a Set view of the mappings contained in this map.
equals?(Object o) Compares the specified object with this map for equality.
get?(Object key) Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
hashCode() Returns the hash code value for this map.
isEmpty() Returns true if this identity hash map contains no key-value mappings.
keySet() Returns an identity-based set view of the keys contained in this map.
put?(K key, V value) Associates the specified value with the specified key in this identity hash map.
putAll?(Map<? extends K,?? extends V> m) Copies all of the mappings from the specified map to this map.
remove?(Object key) Removes the mapping for this key from this map if present.
size() Returns the number of key-value mappings in this identity hash map.
values() Returns a Collection view of the values contained in this map.

Methods declared in class java.util.AbstractMap

METHOD

DESCRIPTION

 toString() Returns a string representation of this map.

Methods declared in interface java.util.Map

METHOD

DESCRIPTION

 compute?(K key, BiFunction<? super K,?? super V,?? extends V> remappingFunction) Attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping).
computeIfAbsent?(K key, Function<? super K,?? extends V> mappingFunction) If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.
computeIfPresent?(K key, BiFunction<? super K,?? super V,?? extends V> remappingFunction) If the value for the specified key is present and non-null, attempts to compute a new mapping given the key and its current mapped value.
forEach?(BiConsumer<? super K,?? super V> action) Performs the given action for each entry in this map until all entries have been processed or the action throws an exception.
getOrDefault?(Object key, V defaultValue) Returns the value to which the specified key is mapped, or defaultValue if this map contains no mapping for the key.
merge?(K key, V value, BiFunction<? super V,?? super V,?? extends V> remappingFunction) If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value.
putIfAbsent?(K key, V value) If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value.
remove?(Object key, Object value) Removes the entry for the specified key only if it is currently mapped to the specified value.
replace?(K key, V value) Replaces the entry for the specified key only if it is currently mapped to some value.
replace?(K key, V oldValue, V newValue) Replaces the entry for the specified key only if currently mapped to the specified value.
replaceAll?(BiFunction<? super K,?? super V,?? extends V> function) Replaces each entry’s value with the result of invoking the given function on that entry until all entries have been processed or the function throws an exception.

IdentityHashMap vs HashMap

  • IdentityHashMap uses the equality operator “==” for comparing keys and values while HashMap uses the equals method for comparing keys and values inside Map.
  • Since IdentityHashMap doesn’t use equals() its comparatively faster than HashMap for an object with expensive equals().
  • IdentityHashMap doesn’t require keys to be immutable as it is not relied on equals().

The below program illustrates the difference between IdentityHashMap and HashMap implementation.

Java




// Java code to demonstrate IdentityHashMap and
// illustration of how it is different from HashMap 
  
import java.util.Map;
import java.util.HashMap;
import java.util.IdentityHashMap;
  
public class IdentityHashMapExample 
{
    public static void main(String[] args) 
    {
        // Creating HashMap and IdentityHashMap objects
        Map<String, String> hm = new HashMap<>();
        Map<String, String> ihm = new IdentityHashMap<>();
  
        // Putting key and value in HashMap and IdentityHashMap Object
        hm.put("hmkey","hmvalue");
        hm.put(new String("hmkey"),"hmvalue1"); 
        ihm.put("ihmkey","ihmvalue"); 
        ihm.put(new String("ihmkey"),"ihmvalue1"); 
          
        // Print Size of HashMap and WeakHashMap Object
        // hm.size() will print 1 since it compares the objects logically
        // and both the keys are same
        System.out.println("Size of HashMap is : "+hm.size());
          
        // ihm.size() will print 2 since it compares the objects by reference
        System.out.println("Size of IdentityHashMap is : "+ihm.size());
  
          
    }
}


Output

Size of HashMap is : 1
Size of IdentityHashMap is : 2

IdentityHashMap is a class in Java that implements the Map interface and uses reference equality to compare keys. It is similar to a regular HashMap, but it uses the == operator to compare keys instead of the equals() method. This means that two keys with the same content but different object references will be treated as distinct keys in an IdentityHashMap.

Here’s an example of how to use IdentityHashMap in Java:

 

Java




import java.util.IdentityHashMap;
  
public class IdentityHashMapExample {
    public static void main(String[] args) {
        IdentityHashMap<String, Integer> map = new IdentityHashMap<>();
  
        // Add key-value pairs to the map
        String key1 = new String("key");
        String key2 = new String("key");
        map.put(key1, 1);
        map.put(key2, 2);
  
        // Get values from the map using the same and different keys
        System.out.println(map.get(key1));      // Output: 1
        System.out.println(map.get(key2));      // Output: 2
        System.out.println(map.get(new String("key")));  // Output: null
    }
}


Output

1
2
null

In this example, we create an IdentityHashMap that maps String keys to Integer values. We add two key-value pairs to the map using two different String objects that have the same content. We then retrieve values from the map using the same and different String objects. We find that we can retrieve values from the map using the two different keys that have the same content, but we cannot retrieve a value using a String object that has the same content but is a different object reference.

Note that IdentityHashMap has a slightly different behavior than a regular HashMap, and is generally only useful in certain situations where reference equality is important. In most cases, a regular HashMap is sufficient and more appropriate.

 



Last Updated : 11 Sep, 2023
Like Article
Save Article
Share your thoughts in the comments
Similar Reads