Difference between HashMap and IdentityHashMap

In this article, the Difference between HashMap and IdentityHashMap, we will discuss IdentityHashMap and difference between IdentityHashMap and HashMap. In previous articles, we have discussed very interesting topics such as How does HashMap work internally, and the difference between HashMap and TreeMap. Important points to be considered for choosing the right map implementation in the Java development. Also, discussed How does TreeMap work internally.

Difference between HashMap and IdentityHashMap

IdentityHashMap in Java

IdentityHashMap implements Map, Serializable and Clonable interfaces and extends AbstractMap class. We must avoid IdentityHashMap class for general purpose. While this class implements Map interface like other map implementation classes such as HashMap, LinkedHashMap, TreeMap, and HashTable. But 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.

Constructors

  • IdentityHashMap(): Constructs a new, empty identity hash map with a default expected maximum size.
  • IdentityHashMap(int expectedMaxSize): Constructs a new, empty map with the specified expected maximum size.
  • IdentityHashMap(Map m): Constructs a new identity hash map containing the key-value mappings in the specified map.

Difference between HashMap and IdentityHashMap

IdentityHashMap in java is available since JDK 4, this class also implements the Map interface like HashMap and LinkedHashMap with a hash table. But the IdentityHashMap uses reference-equality in place of object-equality when comparing keys. Suppose in an IndentityHashMap, there are two keys key1 and key2, there two keys are considered equal if and only if (key1==key2).

But in HashMap implementation, there are two keys key1 and key2, these keys are considered equal if and only if (k1==null ? k2==null: k1.equals(k2)).) Let’s discuss this difference using an example as the following:

Create a Key class

Here I will create a new Key class, that will be used as the key for IdentityHashMap and HashMap.

package com.dineshonjava.algo.map;

/**
 * @author Dinesh.Rajput
 *
 */
public class Key{
	
	final int data = 112;
	private String key;
	
	public Key(String key) {
		super();
		this.key = key;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + data;
		result = prime * result + ((key == null) ? 0 : (key.charAt(0)+"").hashCode());
		System.out.println("hashCode for key: "+ key + " = " + result);
		System.out.println("Index "+ (result & 15));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		System.out.println("equals for key: ");
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Key other = (Key) obj;
		if (data != other.data)
			return false;
		if (key == null) {
			if (other.key != null)
				return false;
		} else if (!key.equals(other.key))
			return false;
		return true;
	}
	
}

In the above Key class, the hashCode() method is overridden so that it returns calculated hash value. The equals() method is overridden so that keys are equal if key and data are equal.

To understand the exact difference between IdentityHashMap and HashMap, we will simply try to write a small program to check what happens when we put some equal elements in HashMap and IdentityHashMap.

Putting value into HashMap

Let’s put same values into HashMap as the following:

package com.dineshonjava.algo.map;

import java.util.HashMap;
import java.util.Map;

/**
* @author Dinesh.Rajput
*
*/
public class HashMapTest {

/**
* @param args
*/
public static void main(String[] args) {
Map<Key, String> map = new HashMap<>();
Key key1 = new Key("Dinesh");
Key key2 = new Key("Dinesh");
Key key3 = new Key("Dinesh");
Key key4 = new Key("Dinesh");
map.put(key1 , "Dinesh");
map.put(key2 , "Dinesh");
map.put(key3 , "Dinesh");
map.put(key4 , "Dinesh");
System.out.println(map.size());
}

}

Note that all key objects are meaningfully equal and hence HashMap doesn’t allow duplicate keys, so it will print the size of Hashmap as 1.

Now let us try above program with IdentityHashMap.

Putting the values in IdentityHashMap

Let’s put same values into IdentityHashMap as the following:

package com.dineshonjava.algo.map;

import java.util.IdentityHashMap;
import java.util.Map;

/**
 * @author Dinesh.Rajput
 *
 */
public class IdentityHashMapTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Map<Key, String> map = new IdentityHashMap<>();
		Key key1 = new Key("Dinesh");
                Key key2 = new Key("Dinesh");
                Key key3 = new Key("Dinesh");
                Key key4 = new Key("Dinesh");
		map.put(key1 , "Dinesh");
		map.put(key2 , "Dinesh");
                map.put(key3 , "Dinesh");
		map.put(key4 , "Dinesh");
		System.out.println(map.size());
	}

}

This will print 4, because, for IdentityHashMap, all keys key1, key2, key3, and key4 are not meaningfully equal. If we refer to one object using 4 references like below,

Key key1 = new Key("Dinesh");
Key key2 = key1;
Key key3 = key1;
Key key4 = key1;

then they will qualify for equality, So the program below will output 1.

package com.dineshonjava.algo.map;

import java.util.IdentityHashMap;
import java.util.Map;

/**
 * @author Dinesh.Rajput
 *
 */
public class IdentityHashMapTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Map<Key, String> map = new IdentityHashMap<>();
                Key key1 = new Key("Dinesh");
                Key key2 = key1;
                Key key3 = key1;
                Key key4 = key1;
		map.put(key1 , "Dinesh");
		map.put(key2 , "Dinesh");
                map.put(key3 , "Dinesh");
		map.put(key4 , "Dinesh");
		System.out.println(map.size());
	}

}

While putting elements, now, all keys key1, key2, key3, and key4 are equal. Now size will be 1.

Hope this article will be able to explain the Difference between HashMap and IdentityHashMap.

Previous
Next