Java IdentityHashMap - IdentityHashMap in Java - Walking Techie

Blog about Java programming, Design Pattern, and Data Structure.

Thursday, March 9, 2017

Java IdentityHashMap - IdentityHashMap in Java

What is IdentityHashMap in Java?

IdentityHashMap implements the Map interface with a hash table, using reference-equality in place of object-equality when comparing keys and values.

In other words, in an IdentityHashMap, two keys k1 and k2 are considered equal if and only if (k1==k2). In normal Map implementations (like HashMap) two keys k1 and k2 are considered equal if and only if (k1==null ? k2==null : k1.equals(k2)).

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 designed for use only in the rare cases wherein reference-equality semantics are required.

Here is the topic that will cover in this post.

  1. IdentityHashMap class Declaration
  2. IdentityHashMap features
  3. Use cases for IdentityHashMap
  4. IdentityHashMap constructors
  5. IdentityHashMap class Methods
  6. Example
  7. Iterate or Traverse over IdentityHashMap
  8. Difference between HashMap and IdentityHashMap

Java IdentityHashMap class Declaration

The IdentityHashMap class extends AbstractMap and implements the Map interface. It is similar to HashMap except that it uses reference equality when comparing elements. IdentityHashMap is a generic class that has this declaration:

public class IdentityHashMap<K,V> extends AbstractMap<K,V>
        implements Map<K,V>, java.io.Serializable, Cloneable

Here, K specifies the type of keys, and V specifies the type of values.

Java IdentityHashMap features

  1. Java IdentityHashMap inherits AbstractMap class.
  2. Java IdentityHashMap implements the Map interface.
  3. Java IdentityHashMap permits one null key and multiple null values.
  4. Java IdentityHashMap can not be used for primitive types, like int, char, etc. We need to use wrapper classes.
  5. This class does not guarantee that the order will remain constant over time.
  6. Java IdentityHashMap is not synchronized.
  7. Java IdentityHashMap is not thread-safe. You can make thread-safe by doing
    Map m = Collections.synchronizedMap(new IdentityHashMap(...));
  8. Java IdentityHashMap implementation provides constant-time performance for the basic operations (get, and put), assuming the hash function disperses the elements properly among the buckets.
  9. Java IdentityHashMap uses linear-probe hash table. IdentityHashMap performance is better than HashMap (which uses chaining rather than linear-probing).
  10. The iterators returned by all of this class's "collection view methods" are fail-fast.

Use cases for IdentityHashMap

  • A typical use of this class is topology-preserving object graph transformations, such as serialization or deep-copying. To perform such a transformation, a program must maintain a "node table" that keeps track of all the object references that have already been processed. The node table must not equate distinct objects even if they happen to be equal.
  • Another typical use of this class is to maintain proxy objects. For example, a debugging facility might wish to maintain a proxy object for each object in the program being debugged.

Java IdentityHashMap constructors

Java IdentityHashMap have five constructors.

Constructor Description
public IdentityHashMap() Constructs an empty identity hash map with a default expected maximum size (21).
public IdentityHashMap(int expectedMaxSize) Constructs an empty map with the specified expected maximum size. Putting more than the expected number of key-value mappings into the map may cause the internal data structure to grow, which may be somewhat time-consuming.
public IdentityHashMap(Map<? extends K, ? extends V> m) Constructs a new identity hash map containing the keys-value mappings in the specified map.

Below code snippet show example to create IdentityHashMap instances using it's constructors.


    IdentityHashMap<Integer, String> identityHashMap1 = new IdentityHashMap<>();

    IdentityHashMap<Integer, String> identityHashMap2 = new IdentityHashMap<>(32);

    IdentityHashMap<Integer, String> identityHashMap3 = new IdentityHashMap<>(identityHashMap1);

    

Java IdentityHashMap methods

IdentityHashMap does not provide own method. IdentityHashMap uses the methods of the HashMap.

Example

Here is a simple program of IdentityHashMap.

package com.walking.techie;

import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

public class IdentityHashMapDemo {

  public static void main(String[] args) {

    IdentityHashMap<Integer, String> identityHashMap = new IdentityHashMap<>();

    identityHashMap.put(100, "Continue");
    identityHashMap.put(200, "OK");
    identityHashMap.put(300, "Multiple Choices");
    identityHashMap.put(302, "Moved Temporarily");
    Integer key = new Integer(400);
    identityHashMap.put(key, "Bad Request");
    identityHashMap.put(401, "Unauthorized");
    identityHashMap.put(500, "Server Error");
    identityHashMap.put(503, "Service Unavailable");

    // size of identityHashMap
    System.out.println("Size of the identityHashMap : " + identityHashMap.size());

    // check identityHashMap is empty or not
    System.out.println("Is identityHashMap Empty? " + identityHashMap.isEmpty());

    // get the value for given Key, compare on reference
    System.out.println("Http message for HttpStatus code 400 is " + identityHashMap.get(key));
    // return null
    System.out.println("Http message for HttpStatus code 401 is " + identityHashMap.get(401));

    // check identityHashMap contain mapping for given key
    System.out
        .println("Is identityHashMap contain mapping for HttpStatus code 400 is " + identityHashMap
            .containsKey(key));
    // return false
    System.out.println("Is identityHashMap contain mapping for HttpStatus code 401 is " + identityHashMap
            .containsKey(401));

    Map<Integer, String> httpStatus = new TreeMap<>();

    httpStatus.put(424, "Failed Dependency");
    httpStatus.put(504, "Gateway Timeout");
    httpStatus.put(409, "Conflict");

    // copy all elements of httpStatus to identityHashMap
    identityHashMap.putAll(httpStatus);

    // print all the elements of the identityHashMap
    System.out.println("\n******All elements of the identityHashMap");
    for (Integer code : identityHashMap.keySet()) {
      System.out.println("Http Status Code : " + code + " Http Message : " + identityHashMap.get(code));
    }

    System.out
        .println("\nSize of the identityHashMap before remove call " + identityHashMap.size());
    // remove the mapping from the identityHashMap for given key
    System.out.println("\nValue of the removed key (503) is : " + identityHashMap.remove(503));
    System.out.println("Size of the identityHashMap before after call " + identityHashMap.size());
    System.out.println("\nValue of the removed key (400) is : " + identityHashMap.remove(key));

    // To check value is present is the identityHashMap
    System.out.println("\nToo Many Requests is present in identityHashMap : " + identityHashMap
        .containsValue("Too Many Requests"));
    System.out.println("Upgrade Required is present in identityHashMap : " + identityHashMap
        .containsValue("Upgrade Required"));

    // Get collection view of this identityHashMap
    Collection<String> httpStatusMessage = identityHashMap.values();
    System.out.println("\n *****Http Status message of the collection view*****");
    for (String message : httpStatusMessage) {
      System.out.println("Http Status Message : " + message);
    }

    // Display key-value pair of element using EntrySet
    Set<Entry<Integer, String>> entrySet = identityHashMap.entrySet();
    Iterator<Entry<Integer, String>> iterator = entrySet.iterator();
    System.out.println("\n *****Display Elements of the identityHashMap using EntrySet*****");
    while (iterator.hasNext()) {
      Entry<Integer, String> entry = iterator.next();
      System.out
          .println("Http Status Code : " + entry.getKey() + " Http Message : " + entry.getValue());
    }
    // create clone of identityHashMap
    Object clonedHashMap = identityHashMap.clone();
    System.out.println("\nCloned identityHashMap : \n" + clonedHashMap);

    // clear all elements of the identityHashMap
    identityHashMap.clear();
    System.out.println("\nSize of the identityHashMap is " + identityHashMap.size());
  }
}

Output of above program is shown below:

Size of the identityHashMap : 8
Is identityHashMap Empty? false
Http message for HttpStatus code 400 is Bad Request
Http message for HttpStatus code 401 is null
Is identityHashMap contain mapping for HttpStatus code 400 is true
Is identityHashMap contain mapping for HttpStatus code 401 is false

******All elements of the identityHashMap
Http Status Code : 300 Http Message : Multiple Choices
Http Status Code : 500 Http Message : Server Error
Http Status Code : 409 Http Message : Conflict
Http Status Code : 400 Http Message : Bad Request
Http Status Code : 424 Http Message : Failed Dependency
Http Status Code : 302 Http Message : Moved Temporarily
Http Status Code : 504 Http Message : Gateway Timeout
Http Status Code : 200 Http Message : OK
Http Status Code : 100 Http Message : Continue
Http Status Code : 401 Http Message : Unauthorized
Http Status Code : 503 Http Message : Service Unavailable

Size of the identityHashMap before remove call 11

Value of the removed key (503) is : null
Size of the identityHashMap before after call 11

Value of the removed key (400) is : Bad Request

Too Many Requests is present in identityHashMap : false
Upgrade Required is present in identityHashMap : false

 *****Http Status message of the collection view*****
Http Status Message : Multiple Choices
Http Status Message : Server Error
Http Status Message : Conflict
Http Status Message : Failed Dependency
Http Status Message : Moved Temporarily
Http Status Message : Gateway Timeout
Http Status Message : OK
Http Status Message : Continue
Http Status Message : Unauthorized
Http Status Message : Service Unavailable

 *****Display Elements of the identityHashMap using EntrySet*****
Http Status Code : 300 Http Message : Multiple Choices
Http Status Code : 500 Http Message : Server Error
Http Status Code : 409 Http Message : Conflict
Http Status Code : 424 Http Message : Failed Dependency
Http Status Code : 302 Http Message : Moved Temporarily
Http Status Code : 504 Http Message : Gateway Timeout
Http Status Code : 200 Http Message : OK
Http Status Code : 100 Http Message : Continue
Http Status Code : 401 Http Message : Unauthorized
Http Status Code : 503 Http Message : Service Unavailable

Cloned identityHashMap :
{300=Multiple Choices, 500=Server Error, 409=Conflict, 424=Failed Dependency, 302=Moved Temporarily, 504=Gateway Timeout, 200=OK, 100=Continue, 401=Unauthorized, 503=Service Unavailable}

Size of the identityHashMap is 0

Iterate or Traverse over IdentityHashMap

1. Iterating IdentityHashMap in java using iterator and KeySet

package com.walking.techie;

import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Set;

public class IdentityHashMapTraversal {
  public static void main(String[] args) {
    IdentityHashMap<Integer, String> identityHashMap = new IdentityHashMap<>();
    identityHashMap.put(100, "Continue");
    identityHashMap.put(400, "Bad Request");
    identityHashMap.put(200, "OK");
    identityHashMap.put(500, "Server Error");
    identityHashMap.put(300, "Multiple Choices");

    // Returns a Set view of the keys contained in this map.
    Set<Integer> set = identityHashMap.keySet();

    // Returns an iterator over the elements in this set.
    Iterator<Integer> itr = set.iterator();
    while (itr.hasNext()) {
      Integer key = itr.next();
      System.out.println("Key=" + key + " Value=" + identityHashMap.get(key));
    }
  }
}

Output of above program is shown below:

Key=200 Value=OK
Key=300 Value=Multiple Choices
Key=500 Value=Server Error
Key=400 Value=Bad Request
Key=100 Value=Continue

2. Iterating IdentityHashMap in java using EntrySet and Java Iterator

package com.walking.techie;

import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class IdentityHashMapTraversal {

  public static void main(String[] args) {
    IdentityHashMap<Integer, String> identityHashMap = new IdentityHashMap<>();
    identityHashMap.put(100, "Continue");
    identityHashMap.put(400, "Bad Request");
    identityHashMap.put(200, "OK");
    identityHashMap.put(500, "Server Error");
    identityHashMap.put(300, "Multiple Choices");

    // Returns a Set view of the mappings contained in this map.
    Set<java.util.Map.Entry<Integer, String>> entry = identityHashMap.entrySet();

    // Returns an iterator over the elements in this set.
    Iterator<Entry<Integer, String>> iterator = entry.iterator();
    while (iterator.hasNext()) {
      Map.Entry<Integer, String> entry2 = (Entry<Integer, String>) iterator.next();
      System.out.println("Key=" + entry2.getKey() + " Value=" + entry2.getValue());
    }
  }
}

Output of above program is shown below:

Key=200 Value=OK
Key=300 Value=Multiple Choices
Key=500 Value=Server Error
Key=400 Value=Bad Request
Key=100 Value=Continue

3. Iterating IdentityHashMap in java using EntrySet and Java for loop

package com.walking.techie;

import java.util.IdentityHashMap;
import java.util.Map.Entry;
import java.util.Set;

public class IdentityHashMapTraversal {

  public static void main(String[] args) {
    IdentityHashMap<Integer, String> identityHashMap = new IdentityHashMap<>();
    identityHashMap.put(100, "Continue");
    identityHashMap.put(400, "Bad Request");
    identityHashMap.put(200, "OK");
    identityHashMap.put(500, "Server Error");
    identityHashMap.put(300, "Multiple Choices");

    Set<Entry<Integer, String>> entrySet = identityHashMap.entrySet();
    for (Entry<Integer, String> entry : entrySet) {
      System.out.println("Key=" + entry.getKey() + " Value=" + entry.getValue());
    }
  }
}

Output of above program is shown below:

Key=200 Value=OK
Key=300 Value=Multiple Choices
Key=500 Value=Server Error
Key=400 Value=Bad Request
Key=100 Value=Continue

4. Iterating IdentityHashMap in java using KeySet and Java for loop

package com.walking.techie;

import java.util.IdentityHashMap;

public class IdentityHashMapTraversal {

  public static void main(String[] args) {
    IdentityHashMap<Integer, String> identityHashMap = new IdentityHashMap<>();
    identityHashMap.put(100, "Continue");
    identityHashMap.put(400, "Bad Request");
    identityHashMap.put(200, "OK");
    identityHashMap.put(500, "Server Error");
    identityHashMap.put(300, "Multiple Choices");

    for (Integer key : identityHashMap.keySet()) {
      System.out.println("Key=" + key + " Value=" + identityHashMap.get(key));
    }
  }
}

Output of above program is shown below:

Key=200 Value=OK
Key=300 Value=Multiple Choices
Key=500 Value=Server Error
Key=400 Value=Bad Request
Key=100 Value=Continue

5. Iterating IdentityHashMap in java using Java 8 forEach and lambda expression

package com.walking.techie;

import java.util.IdentityHashMap;

public class IdentityHashMapTraversal {

  public static void main(String[] args) {
    IdentityHashMap<Integer, String> identityHashMap = new IdentityHashMap<>();
    identityHashMap.put(100, "Continue");
    identityHashMap.put(400, "Bad Request");
    identityHashMap.put(200, "OK");
    identityHashMap.put(500, "Server Error");
    identityHashMap.put(300, "Multiple Choices");

    // using java 8 for each and lambda expression
    identityHashMap.forEach((k, v) -> {
      System.out.println("Key=" + k + " Value=" + v);
    });
  }
}

Output of above program is shown below:

Key=200 Value=OK
Key=300 Value=Multiple Choices
Key=500 Value=Server Error
Key=400 Value=Bad Request
Key=100 Value=Continue

Difference between HashMap and IdentityHashMap

  • HashMap uses equals method for comparing keys and values while IdentityHashMap uses equality operator “==” for comparing keys and values inside map.
  • IdentityHashMap does not use equals() method so it is comparatively faster than HashMap for object with expensive equals() method.
  • IdentityHashMap does not require keys to be immutable as it is not relied on equals() method.

No comments :

Post a Comment