Wednesday, 6 January 2016

How IdentityHashMap Works in Java?

In my previous posts, I explained how How HashMap works in Java, How TreeMap works in Java, How LinkedHashMap works inJava. I recommend you to go through above posts, before reading this.

IdentityHashMap is just like HashMap, only difference is it uses reference equality of keys, while storing <Key, Value> pair. In an IdentityHashMap, two keys k1 and k2 are considered equal if and only if (k1==k2).
public class Employee {
 private int id;
 private String firstName;
 private String lastName;

 public Employee(int id, String firstName, String lastName) {
  super();
  this.id = id;
  this.firstName = firstName;
  this.lastName = lastName;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result
    + ((firstName == null) ? 0 : firstName.hashCode());
  result = prime * result + id;
  result = prime * result
    + ((lastName == null) ? 0 : lastName.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Employee other = (Employee) obj;
  if (firstName == null) {
   if (other.firstName != null)
    return false;
  } else if (!firstName.equals(other.firstName))
   return false;
  if (id != other.id)
   return false;
  if (lastName == null) {
   if (other.lastName != null)
    return false;
  } else if (!lastName.equals(other.lastName))
   return false;
  return true;
 }

 @Override
 public String toString() {
  StringBuilder builder = new StringBuilder();
  builder.append("Employee [id=").append(id).append(", firstName=")
    .append(firstName).append(", lastName=").append(lastName)
    .append("]");
  return builder.toString();
 }

}

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

public class EmployeeTest {
 private static void displayMap(Map<Employee, String> map) {
  Set<Employee> keys = map.keySet();

  for (Employee emp : keys) {
   System.out.println(emp);
  }
 }

 public static void main(String args[]) {
  Employee emp1 = new Employee(1, "Hari Krishna", "Gurram");
  Employee emp2 = new Employee(1, "Hari Krishna", "Gurram");
  Employee emp3 = new Employee(1, "Hari Krishna", "Gurram");
  Employee emp4 = new Employee(1, "Hari Krishna", "Gurram");
  Employee emp5 = new Employee(1, "Hari Krishna", "Gurram");

  Map<Employee, String> hashMap = new HashMap<>();
  Map<Employee, String> identityHashMap = new IdentityHashMap<>();

  hashMap.put(emp1, "Software Engineer");
  hashMap.put(emp2, "Software Engineer");
  hashMap.put(emp3, "Software Engineer");
  hashMap.put(emp4, "Software Engineer");
  hashMap.put(emp5, "Software Engineer");

  identityHashMap.put(emp1, "Software Engineer");
  identityHashMap.put(emp2, "Software Engineer");
  identityHashMap.put(emp3, "Software Engineer");
  identityHashMap.put(emp4, "Software Engineer");
  identityHashMap.put(emp5, "Software Engineer");

  System.out.println("Data in HashMap");
  System.out.println("**************************");
  displayMap(hashMap);

  System.out.println("Data in IdentityHashMap");
  System.out.println("**************************");
  displayMap(identityHashMap);
 }
}


Output
Data in HashMap
**************************
Employee [id=1, firstName=Hari Krishna, lastName=Gurram]
Data in IdentityHashMap
**************************
Employee [id=1, firstName=Hari Krishna, lastName=Gurram]
Employee [id=1, firstName=Hari Krishna, lastName=Gurram]
Employee [id=1, firstName=Hari Krishna, lastName=Gurram]
Employee [id=1, firstName=Hari Krishna, lastName=Gurram]
Employee [id=1, firstName=Hari Krishna, lastName=Gurram]


Please go through the program once, I created 5 Employee instances emp1, emp2, emp3, emp4 and emp5. All the Employee instances have same properties (id=1, firstName=Hari Krishna, lastName=Gurram).

Since HashMap stores the <Key, Value> pair based on equals method of key. Equlas method for Employee instances emp1, emp2, emp3, emp4, emp5 is same for all. HashMap stores only one Employee instance. In case of IdentityHashMap, all emp1, emp2, emp3, emp4 and emp5 are five different objects, reference check for emp1==emp2 is false, so IdentityHashMap store all five employees.
public class EmployeeTest {

 public static void main(String args[]) {
  Employee emp1 = new Employee(1, "Hari Krishna", "Gurram");
  Employee emp2 = new Employee(1, "Hari Krishna", "Gurram");
  Employee emp3 = new Employee(1, "Hari Krishna", "Gurram");
  Employee emp4 = new Employee(1, "Hari Krishna", "Gurram");
  Employee emp5 = new Employee(1, "Hari Krishna", "Gurram");

  System.out.println("emp1.equals(emp2) : " + emp1.equals(emp2));
  System.out.println("emp1.equals(emp3) : " + emp1.equals(emp3));
  System.out.println("emp1.equals(emp4) : " + emp1.equals(emp4));
  System.out.println("emp1.equals(emp5) : " + emp1.equals(emp5));

  System.out.println("emp1==emp2 : " + (emp1 == emp2));
  System.out.println("emp1==emp3 : " + (emp1 == emp3));
  System.out.println("emp1==emp4 : " + (emp1 == emp4));
  System.out.println("emp1==emp5 : " + (emp1 == emp5));
 }
}


Output
emp1.equals(emp2) : true
emp1.equals(emp3) : true
emp1.equals(emp4) : true
emp1.equals(emp5) : true
emp1==emp2 : false
emp1==emp3 : false
emp1==emp4 : false
emp1==emp5 : false


Note
As you observe, IdentityHashMap intentionally violates the 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.


You may like


                                                 Home

No comments:

Post a Comment