equals vs == and HashMap vs IdentityHashMap

== is an operator that checks the object references.
i.e.
String a="waqas";
String b="waqas";

a==b is true because both a & b refer to same object reference "waqas";

.equals() is a method that checks the contents or can be overridden to return the desired results.

String a="waqas";
String b ="waqas";
String c= new String("waqas");
String d= new String("waqas");

a.equals(b) is true, and similarly a.equals(c) and c.equals(d) true
but a==c is not true and similarly a==d, b==c, b==d are not true
HashMap
HashMap uses the .equals() method to perform its operations like checking for duplicate keys....

IdentityHashMap
IdentityHashMap uses == method to perform its operations, as name suggests, it checks identity of the key not the contents.


Example

import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
public class IdentityMapDemo {
public static void main(String[] args) {
Map identityMap = new IdentityHashMap();
Map hashMap = new HashMap();
identityMap.put("a", 1);
identityMap.put(new String("a"), 2);
identityMap.put("a", 3);
hashMap.put("a", 1);
hashMap.put("a", 1);
hashMap.put(new String("a"), 2);
hashMap.put("a", 3);

System.out.println("Identity Map KeySet Size :: " + identityMap.keySet().size());

System.out.println("Hash Map KeySet Size :: " + hashMap.keySet().size());
}
}

Result:
Identity Map KeySet Size :: 2
Hash Map KeySet Size :: 1

Another Differece between HashMap and IdentityHashMap is
The other difference (or a consequence) is that IdentityHashMap does not use hash from
object.hashCode() but uses System.identityHashCode(object).
This is a major difference, because you can use IdentityHashMap for mutable objects for whose hash code changes during the "in map" time frame.

Example: there is Person class with 'name' and 'age' properties and #equals checks for 'name' and 'age' and #hashCode depends on those properties as well.

Person p = new Person("Jan Kowalski");
hashMap = new HashMap();
idHashMap = new IdentityHashMap();
hashMap.put(p, something);
idHashMap.put(p, something);
p.setAge(30);

...and now what?

hashMap.containsKey(p)
-> it is unknown if this is going to return true or false. Sometimes it will return true, sometimes false. This is a bug to put mutable objects into HashMap and changing them later. That will lead to hard to find bugs. On the other hand:
idHashMap.containsKey(p)
--> will always return true as long as this is the same object.

However:
p2 = new Person("Jan Kowalski");
p2.setAge(30);
idHashMap.containsKey(p2)
will always return false.

This is important to know the difference when doing, for example, master-detail form, when some map is used to assign objects which can be modified. Using HashMap for such a case will lead to strange behaviour while IdentityHashMap works fine.

Last, but not least, for big maps packed with objects with expensive #equals and #hashCode methods, IdentityHashMap will perform much better, because none of the two above methods are used.
Difference b/w Object.hashCode and System.identityHashCode(object)

basically System.identityHashCode (Object) always returns different values for different objects Its declared as public static int identityHashCode(Object x)

The hash code for the null reference is zero.


// FileName Test.java
class HashCodeTest
{
 int number;
 public HashCodeTest(int i)
 { this.number=i;}

 public int hashCode() { return this.number; }
}

public class Test
{
 public static void main(String[] args)
 {
     String s1="Namaste"; String s2 = s1;
     System.out.println("s1 "+ s1 + " s2 "+ s2);
     System.out.println("System.identityHashCode(s1)"  + System.identityHashCode(s1));
     System.out.println("System.identityHashCode(s2) "+ System.identityHashCode(s2));
     s1=s1 + " World";
     System.out.println(" s1 "+ s1 + " s2 " + s2);
     System.out.println("System.identityHashCode(s1) " + System.identityHashCode(s1));
     System.out.println("System.identityHashCode(s2) "+ System.identityHashCode(s2));

     HashCodeTest o1 = new HashCodeTest(5);
     HashCodeTest o2 = new HashCodeTest(5);

     System.out.println("");
     System.out.println("First Object : " + o1);
     System.out.println("Second Object : " + o2);
     System.out.println("System.identityHashCode(First_Object) : " + System.identityHashCode(o1));
     System.out.println("System.identityHashCode(Second_Object) : " + System.identityHashCode(o2));
 }
}


the output was something like


s1 Namaste s2 Namaste
System.identityHashCode(s1)1671711
System.identityHashCode(s2) 1671711
s1 Namaste World s2 Namaste
System.identityHashCode(s1) 11394033
System.identityHashCode(s2) 1671711

First Object : HashCodeTest@5
Second Object : HashCodeTest@5
System.identityHashCode(First_Object) : 4384790
System.identityHashCode(Second_Object) : 9634993


Comments