Monday, 24 November 2014

How HashSet works in java

HashSet:

HashSet implements Set interface which does not allow duplicate value.It is not synchronized and is not thread safe.
Definition of duplicate can be quite tricky sometimes.Lets consider two cases here.
  1. In case of primitive types(such as interger, String)
  2. In case of custom defined objects.
In case of primitive types:
In case of primitives type, it is very straight forward.Lets see with help of example:
Lets create a java program:
view plainprint?
  1. package org.arpit.java2blog;
  2. import java.util.HashSet;
  3. public class HashSetMain {
  4.  public static void main(String[] args) {
  5.   HashSet<String> nameSet=new HashSet<String>();
  6.   nameSet.add(“Arpit”);
  7.   nameSet.add(“Arpit”);
  8.   nameSet.add(“john”);
  9.   System.out.println(“size of nameSet=”+nameSet.size());
  10.   System.out.println(nameSet);
  11.  }
  12. }
When you run above program, you will get following output:
view plainprint?
  1. size of nameSet=2
  2. [Arpit, john]
So we tried to add String “Arpit” twice, but as HashSet does not allow duplicate value, it will add “Arpit” once in HashSet
In case of Custom Objects:
For understanding how HashSet will work in case of custom objects, you need to understand hashcode and equals method in java.Lets create a class called Country and implement only equals method in it.
view plainprint?
  1. package org.arpit.java2blog;
  2. public class Country {
  3.  String name;
  4.  long population;
  5.  public String getName() {
  6.   return name;
  7.   }
  8.  public void setName(String name){
  9.   this.name = name;
  10.  }
  11.  public long getPopulation() {
  12.   return population;
  13.  }
  14.  public void setPopulation(long population) {
  15.   this.population = population;
  16.  }
  17.  public String toString()
  18.  {
  19.   return name;
  20.  }
  21.  @Override
  22.  public boolean equals(Object obj) {
  23.   if (this == obj)
  24.    return true;
  25.   if (obj == null)
  26.    return false;
  27.   if (getClass() != obj.getClass())
  28.    return false;
  29.   Country other = (Country) obj;
  30.   if (name == null) {
  31.    if (other.name != null)
  32.     return false;
  33.   } else if (!name.equals(other.name))
  34.    return false;
  35.   return true;
  36.  }
  37. }
create main class:
view plainprint?
  1. package org.arpit.java2blog;
  2. import java.util.HashSet;
  3. public class HashSetCountryMain {
  4.  public static void main(String[] args)
  5.  {
  6.   HashSet<Country> countrySet=new HashSet<Country>();
  7.   Country india1=new Country();
  8.   india1.setName(“India”);
  9.   Country india2=new Country();
  10.   india2.setName(“India”);
  11.   countrySet.add(india1);
  12.   countrySet.add(india2);
  13.   System.out.println(“size of nameSet=”+countrySet.size());
  14.   System.out.println(countrySet);
  15.  }
  16. }
When you run above program, you will get following output:
view plainprint?
  1. size of nameSet=2
  2. [India, India]
Now you must be wondering even through two objects are equal why HashSet contains two values instead of one.This is because First HashSet calculates hashcode for that key object, if hashcodes are same then only it checks for equals method and because hashcode for above two country objects uses default hashcode method,Both will have different memory address hence different hashcode.
Now lets add hashcode method in above Country class
view plainprint?
  1. @Override
  2.  public int hashCode() {
  3.   final int prime = 31;
  4.   int result = 1;
  5.   result = prime * result + ((name == null) ? 0 : name.hashCode());
  6.   return result;
  7.  }
Run above main program again, you will get following output:
view plainprint?
  1. size of nameSet=1
  2. [India]
So now we have good understanding of HashSet, lets see its internal representation:

Internal working of HashSet:

When you add any duplicate element to HashSet, add() method returns false and do not add duplicate element to HashSet.
How add method return false? For this, we need to see HashSet’s add method in JavaAPI
view plainprint?
  1. public class HashSet<E>
  2.     extends AbstractSet<E>
  3.     implements Set<E>, Cloneable, java.io.Serializable
  4. {
  5.     private transient HashMap<E,Object> map;
  6.     // PRESENT is dummy value which will be used as value in map
  7.     private static final Object PRESENT = new Object();
  8.     /**
  9.      * Constructs a empty map.so hash
  10.      * 
  11.      */
  12.     public HashSet() {
  13.         map = new HashMap<E,Object>();
  14.     }
  15.     // return false if e is already present in HashSet
  16.     public boolean add(E e) {
  17.         return map.put(e, PRESENT)==null;
  18.     }
  19.     // other HashSet methods
  20. }
So from above code, It is clear that HashSet uses HashMap for checking duplicate elements.As we know that in HashMap , key should be unique. So HashSet uses this concept, When element is added to HashSet, it is added to internal HashMap as Key.This HashMap required some value so a dummy Object(PRESENT) is used as value in this HashMap.
PRESENT is dummy value which is used value for internal map.
Lets see add method:
view plainprint?
  1. // return false if e is already present in HashSet
  2.    public boolean add(E e) {
  3.     return map.put(e, PRESENT)==null;
  4.    }
So here there will be two cases
  • map.put(e,PRESENT) will return null, if element not present in that map. So map.put(e, PRESENT) == null will return true ,hence add method will return true and element will be added in HashSet.
  • map.put(e,PRESENT) will return old value ,if element is already present in that map. So  map.put(e, PRESENT) == null will return false, hence add method will return false and element will not be added in HashSet.

Difference between ArrayList and Vector in java

ArrayList

  • ArrayList is implementation of list interface.
  • ArrayList is not synchonized(so not thread safe)
  • ArrayList is implemented using array as internal data structure.It can be dynamically resized .
  • ArrayList increases half of its size when its size is increased.

Vector

  • Vector is implementation of list interface.
  • Vector is synchonized(so thread safe)
  • Vector is implemented using array as internal data structure.It can be dynamically resized.
  • Vector doubles size of array when its size is increased.

ArrayList vs Vector:

Parameter Vector ArrayList
Synchonized Yes No
ThreadSafe Yes No
Performance It is slower than arraylist It is faster than Vector
Changes in internal  size of array when  resized Vector doubles size of its internal  array when its size is increased ArrayList increases half of its size when its size is increased.

Which is better? ArrayList or Vector?

It actually depends on our need.Vector is slower than ArrayList as its methods are synchronized so if we don’t work in multi threaded environment then ArrayList is better choice.

Best Practice:

When we initialize ArrayList or Vector,always initialize with largest capacity java program will need as incrementing size is costlier operation.

Can we synchronize ArrayList?

Yes,ArrayList can also be synchonized with help of method Collections.synchronizedList(arraylist)

For more Visit: http://www.quontrasolutions.com/blog/category/java

Comparable in java

Comparable interface:

Class whose objects to be sorted must implement this interface.In this,we have to implement compareTo(Object) method.
For example:
view plainprint?
  1. public class Country implements Comparable<Country>{
  2.        @Override
  3.     public int compareTo(Country country) {
  4.         return (this.countryId < country.countryId ) ? -1: (this.countryId > country.countryId ) ? 1:0 ;
  5. }}
If any class implements comparable inteface then collection of that object can be sorted automatically using Collection.sort() or Arrays.sort().Object will be sort on the basis of compareTo method in that class.
Objects which implement Comparable in java can be used as keys in a SortedMap like TreeMap or SortedSet like TreeSet without implementing any other interface.
Sorting logic must be in same class whose objects are being sorted. Hence this is called natural ordering of objects

Java code:

For Comparable:

We will create class country having attribute id and name.This class will implement Comparable interface and implement CompareTo method to sort collection of country object by id.
1. Country.java
view plainprint?
  1. package org.arpit.java2blog;
  2. //If this.cuntryId < country.countryId:then compare method will return -1
  3. //If this.countryId > country.countryId:then compare method will return 1
  4. //If this.countryId==country.countryId:then compare method will return 0
  5. public class Country implements Comparable<Country>{
  6.     int countryId;
  7.     String countryName;
  8.     public Country(int countryId, String countryName) {
  9.         super();
  10.         this.countryId = countryId;
  11.         this.countryName = countryName;
  12.     }
  13.     @Override
  14.     public int compareTo(Country country) {
  15.        return (this.countryId < country.countryId ) ? -1: (this.countryId > country.countryId ) ? 1:0 ;
  16.     }
  17.     public int getCountryId() {
  18.         return countryId;
  19.     }
  20.     public void setCountryId(int countryId) {
  21.         this.countryId = countryId;
  22.     }
  23.     public String getCountryName() {
  24.         return countryName;
  25.     }
  26.     public void setCountryName(String countryName) {
  27.         this.countryName = countryName;
  28.     }
  29. }
2.ComparableMain.java
view plainprint?
  1. package org.arpit.java2blog;
  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4. import java.util.List;
  5. public class ComparableMain {
  6.  /**
  7.   * @author Arpit Mandliya
  8.   */
  9.  public static void main(String[] args) {
  10.    Country indiaCountry=new Country(1“India”);
  11.    Country chinaCountry=new Country(4“China”);
  12.    Country nepalCountry=new Country(3“Nepal”);
  13.    Country bhutanCountry=new Country(2“Bhutan”);
  14.          List<Country> listOfCountries = new ArrayList<Country>();
  15.          listOfCountries.add(indiaCountry);
  16.          listOfCountries.add(chinaCountry);
  17.          listOfCountries.add(nepalCountry);
  18.          listOfCountries.add(bhutanCountry);
  19.          System.out.println(“Before Sort  : “);
  20.          for (int i = 0; i < listOfCountries.size(); i++) {
  21.     Country country=(Country) listOfCountries.get(i);
  22.     System.out.println(“Country Id: “+country.getCountryId()+“||”+“Country name: “+country.getCountryName());
  23.    }
  24.          Collections.sort(listOfCountries);
  25.          System.out.println(“After Sort  : “);
  26.          for (int i = 0; i < listOfCountries.size(); i++) {
  27.     Country country=(Country) listOfCountries.get(i);
  28.     System.out.println(“Country Id: “+country.getCountryId()+“|| “+“Country name: “+country.getCountryName());
  29.    }
  30.  }
  31. }
Output:
view plainprint?
  1. Before Sort  :
  2. Country Id: 1||Country name: India
  3. Country Id: 4||Country name: China
  4. Country Id: 3||Country name: Nepal
  5. Country Id: 2||Country name: Bhutan
  6. After Sort  :
  7. Country Id: 1|| Country name: India
  8. Country Id: 2|| Country name: Bhutan
  9. Country Id: 3|| Country name: Nepal
  10. Country Id: 4|| Country name: China

Difference between Comparator and Comparable in java

Comparable interface:

Class whose objects to be sorted must implement this interface.In this,we have to implement compareTo(Object) method.
For example:
view plainprint?
  1. public class Country implements Comparable<Country>{
  2.        @Override
  3.     public int compareTo(Country country) {
  4.         return (this.countryId < country.countryId ) ? -1: (this.countryId > country.countryId ) ? 1:0 ;
  5. }}
If any class implements comparable inteface then collection of that object can be sorted automatically using Collection.sort() or Arrays.sort().Object will be sort on the basis of compareTo method in that class.
Objects which implement Comparable in java can be used as keys in a SortedMap like TreeMap or SortedSet like TreeSet without implementing any other interface.

Comparator interface:

Class whose objects to be sorted do not need to implement this interface.Some third class can implement this interface to sort.e.g.CountrySortByIdComparator class can implement Comparator interface to sort collection of country object by id. For example:
view plainprint?
  1. public class CountrySortByIdComparator implements Comparator<Country>{
  2.     @Override
  3.     public int compare(Country country1, Country country2) {
  4.         return (country1.getCountryId() < country2.getCountryId() ) ? -1: (country1.getCountryId() > country2.getCountryId() ) ? 1:0 ;
  5.     }
  6. }
Using Comparator interface,we can write different sorting based on different attributes of objects to be sorted.You can use anonymous comparator to compare at particular line of code. For example:
view plainprint?
  1.          Country indiaCountry=new Country(1, “India”);
  2.          Country chinaCountry=new Country(4, “China”);
  3.          Country nepalCountry=new Country(3, “Nepal”);
  4.          Country bhutanCountry=new Country(2, “Bhutan”);
  5.          List<Country> listOfCountries = new ArrayList<Country>();
  6.          listOfCountries.add(indiaCountry);
  7.          listOfCountries.add(chinaCountry);
  8.          listOfCountries.add(nepalCountry);
  9.          listOfCountries.add(bhutanCountry);
  10.  //Sort by countryName
  11.             Collections.sort(listOfCountries,new Comparator<Country>() {
  12.                 @Override
  13.                 public int compare(Country o1, Country o2) {
  14.                     return o1.getCountryName().compareTo(o2.getCountryName());
  15.                 }
  16.             });

Comparator vs Comparable

Parameter Comparable Comparator
Sorting logic Sorting logic must be in same class whose objects are being sorted. Hence this is called natural ordering of objects Sorting logic is in separate class. Hence we can write different sorting based on different attributes of objects to be sorted. E.g. Sorting using id,name etc.
Implementation Class whose objects to be sorted must implement this interface.e.g Country class needs to implement comparable to collection of country object by id Class whose objects to be sorted do not need to implement this interface.Some other class can implement this interface. E.g.-CountrySortByIdComparator class can implement Comparator interface to sort collection of country object by id
Sorting method int compareTo(Object o1)
This method compares this object with o1 object and returns  a integer.Its value has following meaning
1. positive – this object is greater than o1
2. zero – this object equals to o1
3. negative – this object is less than o1
int compare(Object o1,Object o2)
This method compares o1 and o2 objects. and returns  a integer.Its value has following meaning.
1. positive – o1 is greater than o2
2. zero – o1 equals to o2
3. negative – o1 is less than o1
Calling method Collections.sort(List)
Here objects will be sorted on the basis of CompareTo method
Collections.sort(List, Comparator)
Here objects will be sorted on the basis of Compare method in Comparator
Package Java.lang.Comparable Java.util.Comparator

Java code:

For Comparable:

We will create class country having attribute id and name.This class will implement Comparable interface and implement CompareTo method to sort collection of country object by id.
1. Country.java
view plainprint?
  1. package org.arpit.javapostsforlearning;
  2. //If this.cuntryId < country.countryId:then compare method will return -1
  3. //If this.countryId > country.countryId:then compare method will return 1
  4. //If this.countryId==country.countryId:then compare method will return 0
  5. public class Country implements Comparable<Country>{
  6.     int countryId;
  7.     String countryName;
  8.     public Country(int countryId, String countryName) {
  9.         super();
  10.         this.countryId = countryId;
  11.         this.countryName = countryName;
  12.     }
  13.     @Override
  14.     public int compareTo(Country country) {
  15.        return (this.countryId < country.countryId ) ? -1: (this.countryId > country.countryId ) ? 1:0 ;
  16.     }
  17.     public int getCountryId() {
  18.         return countryId;
  19.     }
  20.     public void setCountryId(int countryId) {
  21.         this.countryId = countryId;
  22.     }
  23.     public String getCountryName() {
  24.         return countryName;
  25.     }
  26.     public void setCountryName(String countryName) {
  27.         this.countryName = countryName;
  28.     }
  29. }
2.ComparableMain.java
view plainprint?
  1. package org.arpit.javapostsforlearning;
  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4. import java.util.List;
  5. public class ComparableMain {
  6.  /**
  7.   * @author Arpit Mandliya
  8.   */
  9.  public static void main(String[] args) {
  10.    Country indiaCountry=new Country(1, “India”);
  11.    Country chinaCountry=new Country(4, “China”);
  12.    Country nepalCountry=new Country(3, “Nepal”);
  13.    Country bhutanCountry=new Country(2, “Bhutan”);
  14.          List<Country> listOfCountries = new ArrayList<Country>();
  15.          listOfCountries.add(indiaCountry);
  16.          listOfCountries.add(chinaCountry);
  17.          listOfCountries.add(nepalCountry);
  18.          listOfCountries.add(bhutanCountry);
  19.          System.out.println(“Before Sort  : “);
  20.          for (int i = 0; i < listOfCountries.size(); i++) {
  21.     Country country=(Country) listOfCountries.get(i);
  22.     System.out.println(“Country Id: “+country.getCountryId()+”||”+”Country name: “+country.getCountryName());
  23.    }
  24.          Collections.sort(listOfCountries);
  25.          System.out.println(“After Sort  : “);
  26.          for (int i = 0; i < listOfCountries.size(); i++) {
  27.     Country country=(Country) listOfCountries.get(i);
  28.     System.out.println(“Country Id: “+country.getCountryId()+”|| “+”Country name: “+country.getCountryName());
  29.    }
  30.  }
  31. }
Output:
view plainprint?
  1. Before Sort  :
  2. Country Id: 1||Country name: India
  3. Country Id: 4||Country name: China
  4. Country Id: 3||Country name: Nepal
  5. Country Id: 2||Country name: Bhutan
  6. After Sort  :
  7. Country Id: 1|| Country name: India
  8. Country Id: 2|| Country name: Bhutan
  9. Country Id: 3|| Country name: Nepal
  10. Country Id: 4|| Country name: China

For Comparator:

We will create class country having attribute id and name and will create another class CountrySortByIdComparator which will implement Comparator interface and implement compare method to sort collection of country object by id and we will also see how to use anonymous comparator.
1.Country.java
view plainprint?
  1. package org.arpit.javapostsforlearning;
  2. public class Country{
  3.     int countryId;
  4.     String countryName;
  5.     public Country(int countryId, String countryName) {
  6.         super();
  7.         this.countryId = countryId;
  8.         this.countryName = countryName;
  9.     }
  10.     public int getCountryId() {
  11.         return countryId;
  12.     }
  13.     public void setCountryId(int countryId) {
  14.         this.countryId = countryId;
  15.     }
  16.     public String getCountryName() {
  17.         return countryName;
  18.     }
  19.     public void setCountryName(String countryName) {
  20.         this.countryName = countryName;
  21.     }
  22. }
2.CountrySortbyIdComparator.java
view plainprint?
  1. package org.arpit.javapostsforlearning;
  2. import java.util.Comparator;
  3. //If country1.getCountryId()<country2.getCountryId():then compare method will return -1
  4. //If country1.getCountryId()>country2.getCountryId():then compare method will return 1
  5. //If country1.getCountryId()==country2.getCountryId():then compare method will return 0
  6.  public class CountrySortByIdComparator implements Comparator<Country>{
  7.     @Override
  8.     public int compare(Country country1, Country country2) {
  9.         return (country1.getCountryId() < country2.getCountryId() ) ? -1: (country1.getCountryId() > country2.getCountryId() ) ? 1:0 ;
  10.     }
  11. }
3.ComparatorMain.java
view plainprint?
  1. package org.arpit.javapostsforlearning;
  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4. import java.util.Comparator;
  5. import java.util.List;
  6. public class ComparatorMain {
  7.  /**
  8.   * @author Arpit Mandliya
  9.   */
  10.  public static void main(String[] args) {
  11.    Country indiaCountry=new Country(1, “India”);
  12.    Country chinaCountry=new Country(4, “China”);
  13.    Country nepalCountry=new Country(3, “Nepal”);
  14.    Country bhutanCountry=new Country(2, “Bhutan”);
  15.          List<Country> listOfCountries = new ArrayList<Country>();
  16.          listOfCountries.add(indiaCountry);
  17.          listOfCountries.add(chinaCountry);
  18.          listOfCountries.add(nepalCountry);
  19.          listOfCountries.add(bhutanCountry);
  20.          System.out.println(“Before Sort by id : “);
  21.          for (int i = 0; i < listOfCountries.size(); i++) {
  22.     Country country=(Country) listOfCountries.get(i);
  23.     System.out.println(“Country Id: “+country.getCountryId()+”||”+”Country name: “+country.getCountryName());
  24.    }
  25.          Collections.sort(listOfCountries,new CountrySortByIdComparator());
  26.          System.out.println(“After Sort by id: “);
  27.          for (int i = 0; i < listOfCountries.size(); i++) {
  28.     Country country=(Country) listOfCountries.get(i);
  29.     System.out.println(“Country Id: “+country.getCountryId()+”|| “+”Country name: “+country.getCountryName());
  30.    }
  31.          //Sort by countryName
  32.          Collections.sort(listOfCountries,new Comparator<Country>() {
  33.     @Override
  34.     public int compare(Country o1, Country o2) {
  35.      return o1.getCountryName().compareTo(o2.getCountryName());
  36.     }
  37.    });
  38.    System.out.println(“After Sort by name: “);
  39.          for (int i = 0; i < listOfCountries.size(); i++) {
  40.     Country country=(Country) listOfCountries.get(i);
  41.     System.out.println(“Country Id: “+country.getCountryId()+”|| “+”Country name: “+country.getCountryName());
  42.    }
  43.  }
  44. }
Output:
view plainprint?
  1. Before Sort by id :
  2. Country Id: 1||Country name: India
  3. Country Id: 4||Country name: China
  4. Country Id: 3||Country name: Nepal
  5. Country Id: 2||Country name: Bhutan
  6. After Sort by id:
  7. Country Id: 1|| Country name: India
  8. Country Id: 2|| Country name: Bhutan
  9. Country Id: 3|| Country name: Nepal
  10. Country Id: 4|| Country name: China
  11. After Sort by name:
  12. Country Id: 2|| Country name: Bhutan
  13. Country Id: 4|| Country name: China
  14. Country Id: 1|| Country name: India
  15. Country Id: 3|| Country name: Nepal

Difference between HashMap and HashSet in java

HashMap

HashMap implements Map interface which maps key to value.It is not synchronized and is not thread safe.Duplicate keys are not allowed and null keys as well as values are allowed. For more details, you can also read How HashMap works in java.
view plainprint?
  1. HashMap<Interger,String> employeeHashmap=new HashMap<Integer,String>();
  2. employeeHashmap.put(1,”Arpit”);
  3. employeeHashmap.put(2,”John”);

HashSet

HashSet implements Set interface which does not allow duplicate value.It is not synchronized and is not thread safe.For more details, you can also read How HashSet works in java.
view plainprint?
  1. HashSet<String> employeeSet=new HashSet<String>();
  2. employeeSet.add(“Arpit”);
  3. employeeSet.add(“Arpit”);
  4. employeeSet.add(“john”);
Above employeeSet will have 2 elements in it as Set does not allow duplicate values.
add method is used to add element to HashSet.If It return true then element is added successfully but if it return false then you are trying to insert duplicate value.
view plainprint?
  1. public boolean add(Object o)
One main thing about HashSet is objects which we are going to add in HashSet must implement Hashcode() and equals() method so that we can check for duplicate values.If we are adding custom objects to HashSet then we must override() Hashcode() and equals() method according to our need.If we do not override then object will take default implementation which may not desirable.

HashMap vs HashSet:


Parameter HashMap HashSet
Interface This is core difference among them.HashMap implements Map interface HashSet implement Set interface
Method for storing data It stores data in a form of key->value pair.So it uses put(key,value) method for storing data It uses add(value) method for storing data
Duplicates HashMap allows duplicate value but not duplicate keys HashSet does not allow duplicate values.
Performance It is faster than hashset as values are stored with unique keys It is slower than HashMap
HashCode Calculation In hash map hashcode value is calculated using key object In this,hashcode is calculated on the basis of value object.Hashcode can be same for two value object so we have to implement equals() method.If equals() method return false then two objects are different.

How HashMap works in java



Most common interview questions are “How HashMap works in java”, “How get and put method of HashMap work internally”. Here I am trying to explain internal functionality with an easy example. Rather than going through theory, we will start with example first, so that you will get better understanding and then we will see how get and put function work in java.
Lets take a very simple example. I have a Country class, we are going to use Country class object as key and its capital name(string) as value. Below example will help you to understand, how these key value pair will be stored in hashmap.
1. Country.java 
view plainprint?
  1. package org.arpit.java2blog;
  2. public class Country {
  3.  String name;
  4.  long population;
  5.  public Country(String name, long population) {
  6.   super();
  7.   this.name = name;
  8.   this.population = population;
  9.  }
  10.  public String getName() {
  11.   return name;
  12.  }
  13.  public void setName(String name) {
  14.   this.name = name;
  15.  }
  16.  public long getPopulation() {
  17.   return population;
  18.  }
  19.  public void setPopulation(long population) {
  20.   this.population = population;
  21.  }
  22.  // If length of name in country object is even then return 31(any random number) and if odd then return 95(any random number).
  23.  // This is not a good practice to generate hashcode as below method but I am doing so to give better and easy understanding of hashmap.
  24.  @Override
  25.  public int hashCode() {
  26.   if(this.name.length()%2==0)
  27.    return 31;
  28.   else
  29.    return 95;
  30.  }
  31.  @Override
  32.  public boolean equals(Object obj) {
  33.   Country other = (Country) obj;
  34.    if (name.equalsIgnoreCase((other.name)))
  35.    return true;
  36.   return false;
  37.  }
  38. }
If you want to understand more about hashcode and equals method of object, you may refer hashcode() and equals() method in java
2. HashMapStructure.java(main class)
view plainprint?
  1. import java.util.HashMap;
  2. import java.util.Iterator;
  3. public class HashMapStructure {
  4.     /**
  5.      * @author Arpit Mandliya
  6.      */
  7.     public static void main(String[] args) {
  8.         Country india=new Country(“India”,1000);
  9.         Country japan=new Country(“Japan”,10000);
  10.         Country france=new Country(“France”,2000);
  11.         Country russia=new Country(“Russia”,20000);
  12.         HashMap<country tring=“”> countryCapitalMap=new HashMap<country tring=“”>();
  13.         countryCapitalMap.put(india,“Delhi”);
  14.         countryCapitalMap.put(japan,“Tokyo”);
  15.         countryCapitalMap.put(france,“Paris”);
  16.         countryCapitalMap.put(russia,“Moscow”);
  17.         Iterator<country> countryCapitalIter=countryCapitalMap.keySet().iterator();//put debug point at this line
  18.         while(countryCapitalIter.hasNext())
  19.         {
  20.             Country countryObj=countryCapitalIter.next();
  21.             String capital=countryCapitalMap.get(countryObj);
  22.             System.out.println(countryObj.getName()+“—-“+capital);
  23.             }
  24.         }
  25. }
  26. </country></country></country>
Now put debug point at line 23 and right click on project->debug as-> java application. Program will stop execution at line 23 then right click on countryCapitalMap then select watch.You will be able to see structure as below.
Now From above diagram, you can observe following points
    1. There is an Entry[] array called table which has size 16.
    2. This table stores Entry class’s object. HashMap class has a inner class called Entry.This Entry have key value as instance variable. Lets see structure of entry class Entry Structure.
view plainprint?
  1. static class Entry implements Map.Entry
  2. {
  3.         final K key;
  4.         V value;
  5.         Entry next;
  6.         final int hash;
  7.         …//More code goes here
  8. }
  1. Whenever we try to put any key value pair in hashmap, Entry class object is instantiated for key value and that object will be stored in above mentioned Entry[](table). Now you must be wondering, where will above created Enrty object get stored(exact position in table). The answer  is, hash code is calculated for a key by calling Hascode() method. This hashcode is used to calculate index for above Entry[] table.
  2. Now, If you see at array index 10 in above diagram, It has an Entry object named HashMap$Entry.
  3. We have put 4 key-values in hashmap but it seems to have only 2!!!!This is because if two objects have same hashcode, they will be stored at same index. Now question arises how? It stores objects in a form of LinkedList(logically).
So how hashcode of above country key-value pairs are calculated.
view plainprint?
  1. Hashcode for Japan = 95 as its length is odd.
  2. Hashcode for India =95 as its length is odd
  3. HashCode for Russia=31 as its length is even.
  4. HashCode for France=31 as its length is even.
Below diagram will explain LinkedList concept clearly.
So now if you have good understanding of hashmap structure,Lets go through put and get method.

Put :

Lets see implementation of put method:
view plainprint?
  1. /**
  2.   * Associates the specified value with the specified key in this map. If the
  3.   * map previously contained a mapping for the key, the old value is
  4.   * replaced.
  5.   *
  6.   * @param key
  7.   *            key with which the specified value is to be associated
  8.   * @param value
  9.   *            value to be associated with the specified key
  10.   * @return the previous value associated with <tt>key</tt>, or <tt>null</tt>
  11.   *         if there was no mapping for <tt>key</tt>. (A <tt>null</tt> return
  12.   *         can also indicate that the map previously associated
  13.   *         <tt>null</tt> with <tt>key</tt>.)
  14.   */
  15.  public V put(K key, V value) {
  16.   if (key == null)
  17.    return putForNullKey(value);
  18.   int hash = hash(key.hashCode());
  19.   int i = indexFor(hash, table.length);
  20.   for (Entry<k , V> e = table[i]; e != null; e = e.next) {
  21.    Object k;
  22.    if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
  23.     V oldValue = e.value;
  24.     e.value = value;
  25.     e.recordAccess(this);
  26.     return oldValue;
  27.    }
  28.   }
  29.   modCount++;
  30.   addEntry(hash, key, value, i);
  31.   return null;
  32.  }
now lets understand above code step by step
  1. Key object is checked for null. If key is null then it will be stored at table[0] because hashcode for null is always 0.
  2. Key object’s hashcode() method is called and hash code is calculated. This hashcode is used to find index of array for storing Entry object. It may happen sometimes that, this hashcode function is poorly written so JDK designer has put another function called hash() which takes above calculated hash value as argument.If you want to learn more about hash() function, you can refer hash and indexFor method in hashmap.
  3. indexFor(hash,table.length)  is used to calculate exact index in table array for storing the Entry object.
  4. As we have seen in our example, if two key objects have same hashcode(which is known as collision) then it will be stored in form of linkedlist.So here, we will iterate through our linkedlist.
  • If there is no element present at that index which we have just calculated then it will directly put our Entry object at that index.
  • If There is element present at that index then it will iterate until it gets Entry->next as null.Then current Entry object become next node in that linkedlist
  • What if we are putting same key again, logically it should replace old value. Yes,it will do that.While iterating it will check key equality by calling equals() method(key.equals(k)), if this method returns true then it replaces value object with current Entry’s value object.

 Get:

 Lets see implementation of get now:
view plainprint?
  1. /**
  2.   * Returns the value to which the specified key is mapped, or {@code null}
  3.   * if this map contains no mapping for the key.
  4.   *
  5.   * <p>
  6.   * More formally, if this map contains a mapping from a key {@code k} to a
  7.   * value {@code v} such that {@code (key==null ? k==null :
  8.   * key.equals(k))}, then this method returns {@code v}; otherwise it returns
  9.   * {@code null}. (There can be at most one such mapping.)
  10.   *
  11.   * </p><p>
  12.   * A return value of {@code null} does not <i>necessarily</i> indicate that
  13.   * the map contains no mapping for the key; it’s also possible that the map
  14.   * explicitly maps the key to {@code null}. The {@link #containsKey
  15.   * containsKey} operation may be used to distinguish these two cases.
  16.   *
  17.   * @see #put(Object, Object)
  18.   */
  19.  public V get(Object key) {
  20.   if (key == null)
  21.    return getForNullKey();
  22.   int hash = hash(key.hashCode());
  23.   for (Entry<k , V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
  24.    Object k;
  25.    if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
  26.     return e.value;
  27.   }
  28.   return null;
  29.  }
As you got the understanding on put functionality of hashmap. So to understand get functionality is quite simple. If you pass any key to get value object from hashmap.
  1. Key object is checked for null. If key is null then value of Object resides at table[0] will be returned.
  2. Key object’s hashcode() method is called and hash code is calculated.
  3. indexFor(hash,table.length)  is used to calculate exact index in table array using generated hashcode for getting the Entry object.
  4. After getting index in table array, it will iterate through linkedlist and check for key equality by calling equals() method and if it returns true then it returns the value of Entry object else returns null.

Key points to Remeber:

  • HashMap has a inner class called Entry which stores key-value pairs.
  • Above Entry object is stored in Entry[ ](Array) called table
  • An index of table is logically known as bucket and it stores first element of linkedlist
  • Key object’s hashcode() is used to find bucket of that Entry object.
  • If two key object ‘s have same hashcode , they will go in same bucket of table array.
  • Key object ‘s equals() method is used to ensure uniqueness of key object.
  • Value object  ‘s equals() and hashcode() method is not used at all



How HashSet works in java

HashSet:

HashSet implements Set interface which does not allow duplicate value.It is not synchronized and is not thread safe.
Definition of duplicate can be quite tricky sometimes.Lets consider two cases here.
  1. In case of primitive types(such as interger, String)
  2. In case of custom defined objects.
In case of primitive types:
In case of primitives type, it is very straight forward.Lets see with help of example:
Lets create a java program:
view plainprint?
  1. package org.arpit.java2blog;
  2. import java.util.HashSet;
  3. public class HashSetMain {
  4.  public static void main(String[] args) {
  5.   HashSet<String> nameSet=new HashSet<String>();
  6.   nameSet.add(“Arpit”);
  7.   nameSet.add(“Arpit”);
  8.   nameSet.add(“john”);
  9.   System.out.println(“size of nameSet=”+nameSet.size());
  10.   System.out.println(nameSet);
  11.  }
  12. }
When you run above program, you will get following output:
view plainprint?
  1. size of nameSet=2
  2. [Arpit, john]
So we tried to add String “Arpit” twice, but as HashSet does not allow duplicate value, it will add “Arpit” once in HashSet
In case of Custom Objects:
For understanding how HashSet will work in case of custom objects, you need to understand hashcode and equals method in java.Lets create a class called Country and implement only equals method in it.
view plainprint?
  1. package org.arpit.java2blog;
  2. public class Country {
  3.  String name;
  4.  long population;
  5.  public String getName() {
  6.   return name;
  7.   }
  8.  public void setName(String name){
  9.   this.name = name;
  10.  }
  11.  public long getPopulation() {
  12.   return population;
  13.  }
  14.  public void setPopulation(long population) {
  15.   this.population = population;
  16.  }
  17.  public String toString()
  18.  {
  19.   return name;
  20.  }
  21.  @Override
  22.  public boolean equals(Object obj) {
  23.   if (this == obj)
  24.    return true;
  25.   if (obj == null)
  26.    return false;
  27.   if (getClass() != obj.getClass())
  28.    return false;
  29.   Country other = (Country) obj;
  30.   if (name == null) {
  31.    if (other.name != null)
  32.     return false;
  33.   } else if (!name.equals(other.name))
  34.    return false;
  35.   return true;
  36.  }
  37. }
create main class:
view plainprint?
  1. package org.arpit.java2blog;
  2. import java.util.HashSet;
  3. public class HashSetCountryMain {
  4.  public static void main(String[] args)
  5.  {
  6.   HashSet<Country> countrySet=new HashSet<Country>();
  7.   Country india1=new Country();
  8.   india1.setName(“India”);
  9.   Country india2=new Country();
  10.   india2.setName(“India”);
  11.   countrySet.add(india1);
  12.   countrySet.add(india2);
  13.   System.out.println(“size of nameSet=”+countrySet.size());
  14.   System.out.println(countrySet);
  15.  }
  16. }
When you run above program, you will get following output:
view plainprint?
  1. size of nameSet=2
  2. [India, India]
Now you must be wondering even through two objects are equal why HashSet contains two values instead of one.This is because First HashSet calculates hashcode for that key object, if hashcodes are same then only it checks for equals method and because hashcode for above two country objects uses default hashcode method,Both will have different memory address hence different hashcode.
Now lets add hashcode method in above Country class
view plainprint?
  1. @Override
  2.  public int hashCode() {
  3.   final int prime = 31;
  4.   int result = 1;
  5.   result = prime * result + ((name == null) ? 0 : name.hashCode());
  6.   return result;
  7.  }
Run above main program again, you will get following output:
view plainprint?
  1. size of nameSet=1
  2. [India]
So now we have good understanding of HashSet, lets see its internal representation:

Internal working of HashSet:

When you add any duplicate element to HashSet, add() method returns false and do not add duplicate element to HashSet.
How add method return false? For this, we need to see HashSet’s add method in JavaAPI
view plainprint?
  1. public class HashSet<E>
  2.     extends AbstractSet<E>
  3.     implements Set<E>, Cloneable, java.io.Serializable
  4. {
  5.     private transient HashMap<E,Object> map;
  6.     // PRESENT is dummy value which will be used as value in map
  7.     private static final Object PRESENT = new Object();
  8.     /**
  9.      * Constructs a empty map.so hash
  10.      * 
  11.      */
  12.     public HashSet() {
  13.         map = new HashMap<E,Object>();
  14.     }
  15.     // return false if e is already present in HashSet
  16.     public boolean add(E e) {
  17.         return map.put(e, PRESENT)==null;
  18.     }
  19.     // other HashSet methods
  20. }
So from above code, It is clear that HashSet uses HashMap for checking duplicate elements.As we know that in HashMap , key should be unique. So HashSet uses this concept, When element is added to HashSet, it is added to internal HashMap as Key.This HashMap required some value so a dummy Object(PRESENT) is used as value in this HashMap.
PRESENT is dummy value which is used value for internal map.
Lets see add method:
view plainprint?
  1. // return false if e is already present in HashSet
  2.    public boolean add(E e) {
  3.     return map.put(e, PRESENT)==null;
  4.    }
So here there will be two cases
  • map.put(e,PRESENT) will return null, if element not present in that map. So map.put(e, PRESENT) == null will return true ,hence add method will return true and element will be added in HashSet.
  • map.put(e,PRESENT) will return old value ,if element is already present in that map. So  map.put(e, PRESENT) == null will return false, hence add method will return false and element will not be added in HashSet.

hash and indexFor method in HashMap

This post is for the people who already have good understanding of how HashMap works in java and want to understand more about hash and indexFor method.In this post, we will see how hash and indexFor method works internally in hashmap. hash and indexFor methods belong to HashMap class. Why JDK developers need to have another hash function when  key object’s have there own hashcode method.
Lets see code for hash and indexFor

view plainprint?
  1. /**
  2.  * Applies a supplemental hash function to a given hashCode, which
  3.  * defends against poor quality hash functions.  This is critical
  4.  * because HashMap uses power-of-two length hash tables, that
  5.  * otherwise encounter collisions for hashCodes that do not differ
  6.  * in lower bits. Note: Null keys always map to hash 0, thus index 0.
  7.  */
  8. static int hash(int h) {
  9.     // This function ensures that hashCodes that differ only by
  10.     // constant multiples at each bit position have a bounded
  11.     // number of collisions (approximately 8 at default load factor).
  12.     h ^= (h >>> 20) ^ (h >>> 12);
  13.     return h ^ (h >>> 7) ^ (h >>> 4);
  14. }
  15. /**
  16.  * Returns index for hash code h.
  17.  */
  18. static int indexFor(int h, int length) {
  19.     return h & (length-1);
  20. }
As java doc says about hash:
Applies a supplemental hash function to a given hashCode, which defends against poor quality hash functions. This is critical because HashMap uses power-of-two length hash tables, that otherwise encounter collisions for hashCodes that do not differ in lower bits. Note: Null keys always map to hash 0, thus index 0.
Lets understand this with the help of example: Lets say key object’s hashcode() returns only 3 values 31,63 and 95. 31,63 and 95 are integers, so all are 32 bits.
31=00000000000000000000000000011111
63=00000000000000000000000000111111
95=00000000000000000000000001011111
Now lets say our hashmap’s lenth is 16(2^4, Hashmap’s length will be always in power of two)

What if we do not use hash function:

Now if we do not use hash function then
indexFor will return :
31=00000000000000000000000000011111 => 1111=15
63=00000000000000000000000000111111  => 1111=15
95=00000000000000000000000001011111 => 1111=15
Why so?
because when we call indexFor function.It will do AND between 31&15 , 63&15 and 95&15.
For ex. 95&15
00000000000000000000000001011111 &00000000000000000000000000001111
so (2^n-1) will always have sequence of 1’s in it.so what matters here it last n bits as 0&1 is always 0.
In above example, all have 1111 in end that is why they are returning same index.
so although we have different hashcode,each Entry object will be stored at 15 index only.

What if we  use hash function:

If we use hash function then :
On each hashcode, first hash will  be applied.
31=00000000000000000000000000011111 => 00000000000000000000000000011110
63=00000000000000000000000000111111  => 00000000000000000000000000111100
95=00000000000000000000000001011111 => 00000000000000000000000001011010
now after passing new hash to indexFor.It will return :
00000000000000000000000000011110 =>1110=14
00000000000000000000000000111100 =>1100=12
00000000000000000000000001011010 =>1010=10
After applying hash function, above hashcodes are returning different index so hash function is redistributing elements in hashmap thus less collisions and better performance.
The main purpose of hash operation is to make the hashcode differences visible in the least significant bits so that the hashmap elements can be distributed evenly across the buckets

Read more at http://www.java2blog.com/2014/02/hash-and-indexfor-method-in-hashmap.html#L3QvIz8dX3KEIlM3.99

For more Visit: http://www.quontrasolutions.com/blog/category/java