HashMap in java with examples
HashMap
in java is most common Collection which we use
nowadays. It stores entry in key-value pair.
1.
HashMap implements Map interface which
maps key to value.
2.
It is not synchronized and is
not thread safe.
3.
Duplicate keys are not allowed
4.
One null key and multiple null values are
allowed
1
2
3
4
5
|
HashMap<Integer,String>
employeeHashmap=new HashMap<Integer,String>();
employeeHashmap.put(1,"Arpit");
employeeHashmap.put(2,"John");
|
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package org.arpit.java2blog;
import java.util.HashMap;
public class HashMapBuiltMain
{
public static void main(String[] args) {
HashMap<Integer,
String> employeeHashmap = new HashMap<Integer, String>();
employeeHashmap.put(1, "Arpit");
employeeHashmap.put(2,
"John");
employeeHashmap.put(3, "Martin");
employeeHashmap.put(4,
"Vaibhav");
//
Iterating HashMap Using keySet() and for each loop
System.out.println("Iterating HashMap
Using keySet() and for each loop");
System.out.println("-----------------------------");
for (Integer empId :
employeeHashmap.keySet()) {
System.out.println("EmpId:"
+ empId + " and Emp Name:" +
employeeHashmap.get(empId));
}
System.out.println("-----------------------------");
}
}
|
When you run above program, you will get
below output
1
2
3
4
5
6
7
8
9
|
Iterating HashMap Using
keySet() and for each loop
-----------------------------
EmpId:1 and Emp
Name:Arpit
EmpId:2 and Emp Name:John
EmpId:3 and Emp
Name:Martin
EmpId:4 and Emp Name:Vaibhav
-----------------------------
|
Storing Custom objects as Key:
You can store custom objects as Key in HashMap but you
should implement hashcode and equals method, otherwise it may not
work as expected. You may go through hashcode and equal method to
understand it better.
Create a class called Country.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
package org.arpit.java2blog;
public class Country {
String
name;
long population;
public Country(String name, long population)
{
super();
this.name = name;
this.population
= population;
}
public String
getName() {
return name;
}
public void setName(String name) {
this.name
= name;
}
public long
getPopulation() {
return population;
}
public void setPopulation(long population)
{
this.population
= population;
}
@Override
public int
hashCode() {
final int prime = 31;
int
result = 1;
result = prime * result + ((name == null) ?
0 : name.hashCode());
result
= prime * result + (int) (population ^ (population >>> 32));
return result;
}
@Override
public boolean
equals(Object obj) {
if (this == obj)
return
true;
if (obj == null)
return
false;
if (getClass() != obj.getClass())
return
false;
Country other = (Country) obj;
if
(name == null) {
if (other.name != null)
return
false;
} else if (!name.equals(other.name))
return
false;
return true;
}
}
|
Create another class HashMapMain.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
package org.arpit.java2blog;
import java.util.HashMap;
public class HashMapMain {
public static void main(String args[])
{
// HashMap with Country name as key and
capital as value
//
HashMap stores elements in key value pairs
HashMap<String,String>
countryCapitalMap=new HashMap<String,String>();
countryCapitalMap.put("India","Delhi");
countryCapitalMap.put("Japan","Tokyo");
countryCapitalMap.put("France","Paris");
countryCapitalMap.put("Russia","Moscow");
System.out.println("-----------------------------");
//
Iterating HashMap Using keySet() and for each loop
System.out.println("Iterating HashMap
Using keySet() and for each loop");
for
(String countryKey:countryCapitalMap.keySet()) {
System.out.println("Country:"+
countryKey +"
and Capital:"+countryCapitalMap.get(countryKey));
}
System.out.println("-----------------------------");
}
}
|
When you run above program, you will get
below output
1
2
3
4
5
6
7
8
9
|
-----------------------------
Iterating HashMap Using keySet() and for each loop
Country:France
and Capital:Paris
Country:Russia and Capital:Moscow
Country:Japan and Capital:Tokyo
Country:India and Capital:Delhi
-----------------------------
|
HashMap is not synchronized by default but
we can make it synchronized using
1
2
3
|
Collections.synchronizedMap(new
HashMap<String, String>());
|
How HashMap works 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
package org.arpit.java2blog;
public class Country {
String name;
long population;
public Country(String name, long population)
{
super();
this.name = name;
this.population =
population;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getPopulation() {
return
population;
}
public void setPopulation(long population) {
this.population =
population;
}
// If length of name in country object is
even then return 31(any random number) and if odd then return 95(any random
number).
// 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.
@Override
public int hashCode() {
if(this.name.length()%2==0)
return 31;
else
return 95;
}
@Override
public boolean equals(Object obj) {
Country other =
(Country) obj;
if
(name.equalsIgnoreCase((other.name)))
return true;
return false;
}
}
|
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
import java.util.HashMap;
import java.util.Iterator;
public class HashMapStructure
{
/**
*
@author Arpit Mandliya
*/
public
static void main(String[] args) {
Country
india=new Country("India",1000);
Country
japan=new Country("Japan",10000);
Country
france=new Country("France",2000);
Country
russia=new Country("Russia",20000);
HashMap<Country, String> countryCapitalMap=new
HashMap<Country,String>();
countryCapitalMap.put(india,"Delhi");
countryCapitalMap.put(japan,"Tokyo");
countryCapitalMap.put(france,"Paris");
countryCapitalMap.put(russia,"Moscow");
Iterator
countryCapitalIter=countryCapitalMap.keySet().iterator();//put debug point at
this line
while(countryCapitalIter.hasNext())
{
Country
countryObj=countryCapitalIter.next();
String
capital=countryCapitalMap.get(countryObj);
System.out.println(countryObj.getName()+"----"+capital);
}
}
}
|
Now put debug point at line
24 and right click on project->debug as-> java application. Program will
stop execution at line 24 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.
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.
1
2
3
4
5
6
7
8
9
10
|
static class Entry implements
Map.Entry
{
final
K key;
V
value;
Entry
next;
final
int hash;
...//More
code goes here
}
|
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.
1
2
3
4
5
6
|
Hashcode for Japan = 95 as
its length is odd.
Hashcode for India =95 as its
length is odd
HashCode for Russia=31 as its
length is even.
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
/**
* Associates the
specified value with the specified key in this map. If the
* map previously
contained a mapping for the key, the old value is
* replaced.
*
* @param key
* key
with which the specified value is to be associated
* @param value
* value
to be associated with the specified key
* @return the
previous value associated with <tt>key</tt>, or
<tt>null</tt>
*
if there was no mapping for <tt>key</tt>. (A
<tt>null</tt> return
*
can also indicate that the map previously associated
*
<tt>null</tt> with <tt>key</tt>.)
*/
public V put(K key, V value) {
if (key == null)
return
putForNullKey(value);
int hash =
hash(key.hashCode());
int i =
indexFor(hash, table.length);
for (Entry e =
table[i]; e != null; e = e.next) {
Object k;
if (e.hash ==
hash && ((k = e.key) == key || key.equals(k))) {
V
oldValue = e.value;
e.value
= value;
e.recordAccess(this);
return
oldValue;
}
}
modCount++;
addEntry(hash,
key, value, i);
return null;
}
|
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
/**
* Returns the
value to which the specified key is mapped, or {@code null}
* if this map
contains no mapping for the key.
*
*
* More formally, if this map
contains a mapping from a key {@code k} to a
* value {@code v} such that
{@code (key==null ? k==null :
* key.equals(k))}, then this
method returns {@code v}; otherwise it returns
* {@code null}. (There can be
at most one such mapping.)
*
*
* A return value of {@code
null} does not <i>necessarily</i> indicate that
* the map contains no mapping
for the key; it's also possible that the map
* explicitly maps the key to
{@code null}. The {@link #containsKey
* containsKey} operation may
be used to distinguish these two cases.
*
* @see #put(Object, Object)
*/
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash =
hash(key.hashCode());
for (Entry e =
table[indexFor(hash, table.length)]; e != null; e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}
|
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
hash and indexFor method in HashMap
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
Lets see code for hash and indexFor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/**
* 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.
*/
static int hash(int h) {
//
This function ensures that hashCodes that differ only by
//
constant multiples at each bit position have a bounded
//
number of collisions (approximately 8 at default load factor).
h ^=
(h >>> 20) ^ (h >>> 12);
return
h ^ (h >>> 7) ^ (h >>> 4);
}
/**
* Returns index for hash code h.
*/
static int indexFor(int h,
int length) {
return
h & (length-1);
}
|
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.
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)
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
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.
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
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
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
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
Note:
§ If two
key objects have same hashcode, then they will always go to same index in table
array
§ If two
key objects do not have same hashcode then they may or may not go to same index
in table array.
hashcode()
and equals() method in java
These methods can be found
in the Object class and hence available to all java classes.Using these two
methods, an object can be stored or retrieved from a Hashtable, HashMap or
HashSet.
§
hashcode()
§
equals()
hashcode() and equals()
method
hashcode():
You might
know if you put entry in HashMap, first hashcode is calculated and this
hashcode used to find bucket(index) where this entry will get stored in
hashMap.You can read more at How hashMap works in java.
What if you don’t override hashcode method, it will return integer
representation of memory address.
equals():
You have
to override equals method, when you want to define equality between two object.
If you don’t override this method, it will check for reference equality(==)
i.e. if tow reference refers to same object or not
Lets override default implemenation of hashcode() and equals():
You don’t
have to always override these methods, but lets say you want to define equality
of country object based on name, then you need to override equals method and if
you are overriding equals method, you should override hashcode method too.
Below example will make it clear.
Lets see with the help of
example.We have a class called Country
1. Country.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package org.arpit.java2blog;
public class Country {
String name;
long population;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getPopulation() {
return population;
}
public void setPopulation(long population) {
this.population =
population;
}
}
|
This country class have two
basic attributes- name and population.
Now create a class called
“EqualityCheckMain.java”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package org.arpit.java2blog;
public class EqualityCheckMain
{
/**
*
@author arpit mandliya
*/
public static void main(String[] args) {
Country india1=new
Country();
india1.setName("India");
Country india2=new
Country();
india2.setName("India");
System.out.println("Is
india1 is equal to india2:" +india1.equals(india2));
}
}
|
When you run above program,
you will get following output
1
2
3
|
Is india1 is equal to
india2:false
|
In above
program, we have created two different objects and set their name attribute to
“india”.
Because
both references india1 and india2 are pointing to different object, as default
implementation of equals check for ==,equals method is returning false. In real
life, it should have return true because no two countries can have same name.
Now lets override equals
and return true if two country’s name are same.
Add this method to above
country class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() !=
obj.getClass())
return false;
Country other = (Country)
obj;
if (name == null) {
if (other.name != null)
return false;
} else if
(!name.equals(other.name))
return false;
return true;
}
|
and now run
EqualityCheckMain.java again
You will get following
output:
1
2
3
|
Is india1 is equal to
india2:true
|
Now this is because
overriden equals method return true if two country have same name.
One thing to remember here, signature of equals method should be same as above.
One thing to remember here, signature of equals method should be same as above.
Lets put this Country
objects in hashmap:
Here we are going to use
Country class object as key and its capital name(string) as value in HashMap.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package org.arpit.java2blog;
import java.util.HashMap;
import java.util.Iterator;
public class
HashMapEqualityCheckMain {
/**
*
@author Arpit Mandliya
*/
public static void main(String[] args) {
HashMap<Country,String> countryCapitalMap=new
HashMap<Country,String>();
Country india1=new
Country();
india1.setName("India");
Country india2=new
Country();
india2.setName("India");
countryCapitalMap.put(india1, "Delhi");
countryCapitalMap.put(india2, "Delhi");
Iterator
countryCapitalIter=countryCapitalMap.keySet().iterator();
while(countryCapitalIter.hasNext())
{
Country countryObj=countryCapitalIter.next();
String capital=countryCapitalMap.get(countryObj);
System.out.println("Capital of "+
countryObj.getName()+"----"+capital);
}
}
}
|
When you run above program,
you will see following output:
1
2
3
4
|
Capital of India----Delhi
Capital of India----Delhi
|
Now you
must be wondering even through two objects are equal why HashMap contains two
key value pair instead of one.This is because First HashMap uses hashcode to
find bucket 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 override hashcode
method.Add following method to Country class
1
2
3
4
5
6
7
8
9
|
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result +
((name == null) ? 0 : name.hashCode());
return result;
}
|
Now run
HashMapEqualityCheckMain.java again
You will see following
output:
1
2
3
|
Capital of India----Delhi
|
So now
hashcode for above two objects india1 and india2 are same, so Both will be
point to same bucket,now equals method will be used to compare them which
will return true.
This is the reason java doc says “if you override equals() method then you must override hashCode() method”
This is the reason java doc says “if you override equals() method then you must override hashCode() method”
hashcode()
and equals() contracts:
equals():
The equals method
implements an equivalence relation on non-null object references:
§ It
is reflexive: for any non-null reference value x, x.equals(x) should return
true.
§ It
is symmetric: for any non-null reference values x and y, x.equals(y) should
return true if and only if y.equals(x) returns true.
§ It
is transitive: for any non-null reference values x, y, and z, if x.equals(y)
returns true and y.equals(z) returns true, then x.equals(z) should return true.
§ It
is consistent: for any non-null reference values x and y, multiple invocations
of x.equals(y) consistently return true or consistently return false, provided
no information used in equals comparisons on the objects is modified.
§ For any
non-null reference value x, x.equals(null) should return false.
hashcode():
§ Whenever
it is invoked on the same object more than once during an execution of a Java
application, the hashCode method must consistently return the same integer,
provided no information used in equals comparisons on the object is modified.
This integer need not remain consistent from one execution of an application to
another execution of the same application.
§ If two
objects are equal according to the equals(Object) method, then calling the
hashCode method on each of the two objects must produce the same integer
result.
§ It is not
required that if two objects are unequal according to the
equals(java.lang.Object) method, then calling the hashCode method on each of
the two objects must produce distinct integer results. However, the programmer
should be aware that producing distinct integer results for unequal objects may
improve the performance of hash tables.
Key points to remember:
1. If you
are overriding equals method then you should override hashcode() also.
2. If two
objects are equal then they must have same hashcode.
3. If two
objects have same hashcode then they may or may not be equal
4. Always
use same attributes to generate equals and hashcode as in our case we have used
name.
How
to sort HashMap in java by keys and values
Sorting by Keys:
Sorting
by keys can be easily done using TreeMap. You just
need to pass HashMap to the constructor of TreeMap.
1
2
3
|
TreeMap map=new TreeMap(Map
hm);
|
Sorting by values:
We can
use Comparator to
sort it by values.
Sorting by Keys example :
Create Country.java as
below. It should implement Comparable interface
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package
org.arpit.java2blog;
public class Country
implements Comparable {
String name;
long population;
public Country(String name, long population)
{
super();
this.name =
name;
this.population =
population;
}
public String getName() {
return
name;
}
public void setName(String name)
{
this.name =
name;
}
public long getPopulation() {
return
population;
}
public void setPopulation(long population)
{
this.population =
population;
}
@Override
public int compareTo(Object
o) {
Country
country=(Country) o;
return this.getName().compareTo(country.getName());
}
}
|
Create TreeMapCompMain.java
as below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package org.arpit.java2blog;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;
public class TreeMapCompMain
{
public static void main(String[] args)
{
Country india=new
Country("India",1000);
Country
japan=new Country("Japan",10000);
Country
france=new Country("France",2000);
Country
russia=new Country("Russia",20000);
HashMap<Country,
String> countryCapitalMap=new HashMap<Country,String>();
countryCapitalMap.put(india,"Delhi");
countryCapitalMap.put(japan,"Tokyo");
countryCapitalMap.put(france,"Paris");
countryCapitalMap.put(russia,"Moscow");
System.out.println("Sorting
HashMap by passing it to TreeMap constructor");
TreeMap<Country,String>
sortedTreeMapCountryCapital=new TreeMap<Country,String>
(countryCapitalMap);
Iterator
countryCapitalIter=sortedTreeMapCountryCapital.keySet().iterator();//put
debug point at this line
while(countryCapitalIter.hasNext())
{
Country
countryObj=countryCapitalIter.next();
String
capital=countryCapitalMap.get(countryObj);
System.out.println(countryObj.getName()+"----"+capital);
}
}
}
|
When you run program, you
will get below output:
1
2
3
4
5
6
7
|
Sorting HashMap by passing it
to TreeMap constructor
France----Paris
India----Delhi
Japan----Tokyo
Russia----Moscow
|
Sorting by values example:
Here we
will sort HashMap by its values. Here I am taking HashMap to make example
simpler.
Example:
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
package org.arpit.java2blog;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import
java.util.LinkedHashMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
public class HashMapMain {
public static void main(String args[]) {
// HashMap with
Country name as key and capital as value
// HashMap stores
elements in key value pairs
HashMap<String,
String> countryCapitalMap = new HashMap<String, String>();
countryCapitalMap.put("Japan",
"Tokyo");
countryCapitalMap.put("France",
"Paris");
countryCapitalMap.put("Russia",
"Moscow");
countryCapitalMap.put("India",
"Delhi");
System.out.println("-----------------------------");
// Iterating
HashMap Using keySet() and for each loop
System.out.println("Before
Sorting");
System.out.println("-----------------------------");
for (String
countryKey : countryCapitalMap.keySet()) {
System.out.println("Country:" + countryKey + "
and Capital:" + countryCapitalMap.get(countryKey));
}
Set<Entry<String,
String>> countryCapitalEntrySet=countryCapitalMap.entrySet();
List<Entry<String,
String>> entryList=new ArrayList<Entry<String,
String>>(countryCapitalEntrySet);
Collections.sort(entryList,new
Comparator<Entry<String,String>>() {
@Override
public int compare(Entry<String,String>
o1, Entry<String,String> o2) {
return
o1.getValue().compareTo(o2.getValue());
}
});
System.out.println("-----------------------------");
// Using
LinkedHashMop to keep entries in sorted order
LinkedHashMap<String,String>
sortedHashMap=new LinkedHashMap<String,String>();
for
(Entry<String,String> entry:entryList) {
sortedHashMap.put(entry.getKey(), entry.getValue());
}
System.out.println("After
Sorting");
System.out.println("-----------------------------");
// Iterating
sortedHashMap Using keySet() and for each loop
for (String
countryKey : sortedHashMap.keySet()) {
System.out.println("Country:" + countryKey + "
and Capital:" + sortedHashMap.get(countryKey));
}
}
}
|
When you run above program,
you will get below output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
-----------------------------
Before Sorting
-----------------------------
Country:France
and Capital:Paris
Country:Russia
and Capital:Moscow
Country:Japan
and Capital:Tokyo
Country:India
and Capital:Delhi
-----------------------------
After Sorting
-----------------------------
Country:India
and Capital:Delhi
Country:Russia
and Capital:Moscow
Country:France
and Capital:Paris
Country:Japan
and Capital:Tokyo
|
Explanation:
1. Extract
key set from HashMap using keySet() method.
2. Create
ArrayList from above set
3. Sort
above ArrayList using Comparator
4. Create LinkedHashMap from
Sorted list
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.
1
2
3
4
5
|
HashMap<Interger,String> employeeHashmap=new HashMap<Integer,String>();
employeeHashmap.put(1,"Arpit");
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.
1
2
3
4
5
6
|
HashSet employeeSet=new HashSet();
employeeSet.add("Arpit");
employeeSet.add("Arpit");
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.
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.
1
2
3
|
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
|
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.
|
Difference
between Hashtable and HashMap 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 value
are allowed.
1
2
3
4
5
|
HashMap<Interger,String> employeeHashmap=new
HashMap<Integer,String>();
employeeHashmap.put(1,"Arpit");
employeeHashmap.put(2,null); // will work fine
|
Hashtable
Hashtable
implements Map interface which maps key to value.It is synchronized and thread
safe.Duplicate keys are not allowed and null key is not allowed.
1
2
3
4
5
|
Hashtable<Interger,String>
employeeHashmap=new Hashtable<Integer,String>();
employeeHashmap.put(1,"Arpit");
employeeHashmap.put(2,null); //not allowed and will throw NullPointer exception at run time
|
Hashtable vs HashMap:
Parameter
|
Hashtable
|
HashMap
|
ThreadSafe
|
Yes
|
No
|
Synchronized
|
Yes
|
No
|
Performance
|
Due
to theadSafe and Synchronized,it is often slower than HashMap
|
In
single threaded environment, it is much faster than Hashtable.So if you do
not work in multi thread environment ,then hashMap is recommended
|
Null key
|
Do
not allow
|
Allows
null key as well as values
|
Fail fast
|
enumeration
in hashtable is not fail fast
|
Iterator
in hashMap is fail fast
|
Extends
|
It
extends Dictionary class which is quite old
|
It
extends AbstractMap class
|
Alternative
|
No
alternative
|
You
can use ConcurrentHashMap for multi thread environment
|
Some
important points need to be discussed.
§ Synchonized meaning
only one thread can modify one table at one point of time.When any thread
perform update operation on hashtable then it acquires lock on it and other
threads have to wait for lock to be released.
§ Fail-fast iterator
means if one thread is iterating over hashmap and other thread trying to modify
hashmap structurally it will throw ConcurrentModification Exception and fail
immediately.Structurally modification means inserting or deleting elements that
can change structure of map.
Can we synchronize HashMap?
Yes,We can synchonized a
HashMap also with the help of Collections.synchonizedMap(hashmap) so HashMap
can be synchronized by
1
2
3
|
Map map=Collections.synchonizedMap(hashmap)
|
How
to iterate over Map or HashMap in java
1. Using
keyset() and for each loop(Java 5)
2. Using
keyset() and java Iterator
3. Using
EntrySet() and for each loop(Java 5)
4. Using
EntrySet() and java Iterator
if you
remove elements while iterating , then 1st and 3rd option will throw
java.util.ConcurrentModificationException.
If you
understand internal working of HashMap, then it may be easier for you to
iterate an HashMap
Lets take
an example:
1.
IterateMapMain.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
package org.arpit.java2blog;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
public class IterateMapMain {
public static void main(String args[])
{
// HashMap with Country as key and
capital as value
HashMap<String,String>
countryCapitalMap=new HashMap<String,String>();
countryCapitalMap.put("India","Delhi");
countryCapitalMap.put("Japan","Tokyo");
countryCapitalMap.put("France","Paris");
countryCapitalMap.put("Russia","Moscow");
// Iterating Using keySet() and for
each loop
System.out.println("Iterating
Using keySet() and for each loop");
for (String
countryKey:countryCapitalMap.keySet()) {
System.out.println("Country:"+
countryKey +" and Capital:"+countryCapitalMap.get(countryKey));
}
System.out.println("-----------------------------");
// Iterating Using keySet() and
java iterator
System.out.println("Iterating
Using keySet() and java Iterator");
Iterator countryKeySetIterator=countryCapitalMap.keySet().iterator();
while(countryKeySetIterator.hasNext()){
String
countryKey=countryKeySetIterator.next();
System.out.println("Country:"+
countryKey +" and Capital:"+countryCapitalMap.get(countryKey));
}
System.out.println("-----------------------------");
// Iterating Using entrySet() and
for each loop
System.out.println("Iterating
Using entrySet() and for each loop");
for (Entry<String,String>
entry:countryCapitalMap.entrySet()) {
System.out.println("Country:"+
entry.getKey() +" and Capital:"+entry.getValue());
}
System.out.println("-----------------------------");
// Iterating Using entrySet() and
java iterator
System.out.println("Iterating
Using entrySet() and and java Iterator");
Iterator<Entry<String,String>>
entryIterator=countryCapitalMap.entrySet().iterator();
while(entryIterator.hasNext())
{
Entry<String,String>
entry=entryIterator.next();
System.out.println("Country:"+
entry.getKey() +" and Capital:"+entry.getValue());
}
System.out.println("-----------------------------");
}
}
|
Run it and you will get
following output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
Iterating Using keySet() and
for each loop
Country:France
and Capital:Paris
Country:Russia
and Capital:Moscow
Country:Japan
and Capital:Tokyo
Country:India
and Capital:Delhi
-----------------------------
Iterating Using keySet() and
java Iterator
Country:France and
Capital:Paris
Country:Russia and
Capital:Moscow
Country:Japan and Capital:Tokyo
Country:India and
Capital:Delhi
-----------------------------
Iterating Using entrySet()
and for each loop
Country:France
and Capital:Paris
Country:Russia
and Capital:Moscow
Country:Japan
and Capital:Tokyo
Country:India
and Capital:Delhi
-----------------------------
Iterating Using entrySet()
and and java Iterator
Country:France
and Capital:Paris
Country:Russia
and Capital:Moscow
Country:Japan
and Capital:Tokyo
Country:India
and Capital:Delhi
-----------------------------
|