Map(I) interface:

  1. Map is not child interface of Collection.
  2. If we want to represent a group of objects as key-value pairs then we should go for Map.
    Key Value
    101 Kalyan
    102 Chanukya
    103 Hemanth
  3. Both keys and values are objects only.
  4. Duplicate keys are not allowed but values can be duplicated
  5. Each key-value pair is called entry.
  6. Hence Map is considered as a Collection of entry objects.

Map interface methods:

Object put(Object key, Object value)

to add one key-value pair to the map. If the key is already present then old value will be replaced with new value and returns old value.
For Example>
m.put(101, "kalyan"); ---> (returns)null
m.put(102, "chanukya"); ---> (returns)null
m.put(101, "hemanth"); ---> (returns)kalyan

void putAll(Map<? extends K, ? extends V> m);
Object get(Object key) returns the value associated with specified key
Object remove(Object key) returns the entry associated with specified key
boolean containsKey(Object key);
boolean containsValue(Object value);
boolean isEmpty();
int size();
void clear(); all key-pairs will be removed.

Collection views of Map:

Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();

Entry(I) interface:

  1. A Map is a group of key-value pairs and each key-value pair is called an Entry. Hence Map is considering a collection of Entry objects.
  2. Without existing Map object there is no chance of existing Entry Object.
  3. Hence Entry interface is defined inside Map interface.
  4. Entry specific methods and we can apply only on Entry object.
interface Map{
    interface Entry{
        Object getKey()
        Object getValue()
        Object setValue(Object obj)
    }
}

HashMap:

  1. HashMap is a map-based collection which is used to store entries, and it is a implementation class of Map interface and Present since JDK 1.2.
  2. HashMap is hash based, Hence the internal data structure is Hashtable.
  3. HashMap can store heterogeneous data for both key and value and does not maintain any insertion order and it is based on hashcode of keys.
  4. Duplicate keys are not allowed and values can be duplicated.
  5. Null is allowed for key (only one) and null is allowed for values (any no.of times).
  6. HashMap implements Serializable and Cloneable interfaces but not RandomAccess.
  7. HashMap is the best choice if our frequent operation is search operation.
  8. Initial capacity of HashMap is 16.
  9. Fill ratio or load factor is 75%

It has 4 overloaded constructors.

public HashMap ()

creates an empty HashMap object with default initial capacity 16 and default fill ratio 0.75.

public HashMap(int initialCapacity)

creates an empty HashMap object with specified initial capacity and default fillratio 0.75

public HashMap(int initialCapacity, float loadFactor)
public HashMap(Map<? extends K, ? extends V> m)

import java.util.*;
class HashMapDemo{
    public static void main(String[] args){
        HashMap<StringIntegerhm = new HashMap<StringInteger>();
        hm.put("PK"900);
        hm.put("Prabhas"800);
        hm.put("NTR"300);
        hm.put("RC"500);
        System.out.println(hm);
        System.out.println(hm.put("PK"1000));
        Set<Strings = hm.keySet();
        System.out.println(s);
        Collection<Integerc = hm.values();
        System.out.println(c);
        Set s1 = hm.entrySet();
        System.out.println(s1);
        Iterator itr = s1.iterator();
        while(itr.hasNext()){
            Map.Entry m1 = (Map.Entry)itr.next();
            System.out.println(m1.getKey() + " ===== " + m1.getValue());
            if(m1.getKey().equals("PK")){
                m1.setValue(10000);
            }
        }
        System.out.println(hm);
    }
}

Output:
{RC=500, Prabhas=800, PK=900, NTR=300}
900
[RC, Prabhas, PK, NTR]
[500, 800, 1000, 300]
[RC=500, Prabhas=800, PK=1000, NTR=300]
RC ===== 500
Prabhas ===== 800
PK ===== 1000
NTR ===== 300
{RC=500, Prabhas=800, PK=10000, NTR=300}

How to get synchronized version of HashMap object?
By default, HashMap is non synchronized but we can get synchronized version of HashMap using synchronizedMap method of Collections class.

HashMap hm = new HashMap();
Map m1 = Collections.synchronizedMap(hm);

here, m1 is synchronized and hm is non synchronized.

LinkedHashMap:

  1. LinkedHashMap is a map-based collection which is used to store entries, and it is an implementation class of Map interface and it is present since JDK 1.4.
  2. LinkedHashMap is hash based, Hence the internal data structure is Hashtable and LinkedList.
  3. Initial capacity of LinkedHashMap is 16.
  4. Fill ratio or load factor is 75%
  5. LinkedHashMap maintains insertion order.
  6. LinkedHashMap can store single null key.
  7. LinkedHashMap can store heterogeneous data.

It has 4 overloaded constructors.

public LinkedHashMap()
public LinkedHashMap(int initialCapacity)
public LinkedHashMap(Map<? extends K, ? extends V> m)
public LinkedHashMap(int initialCapacity, float loadFactor)


//Program on LinkedHashMap
import java.util.*;
class LinkedHashMapDemo{
    public static void main(String[] args){
        LinkedHashMap<StringIntegerlhm = new LinkedHashMap<StringInteger>();
        lhm.put("PK"900);
        lhm.put("Prabhas"800);
        lhm.put("NTR"300);
        lhm.put("RC"500);
        System.out.println(lhm);
        System.out.println(lhm.put("PK"1000));
        Set<Strings = lhm.keySet();
        System.out.println(s);
        Collection<Integerc = lhm.values();
        System.out.println(c);
        Set s1 = lhm.entrySet();
        System.out.println(s1);
        Iterator itr = s1.iterator();
        while(itr.hasNext()){
            Map.Entry m1 = (Map.Entry)itr.next();
            System.out.println(m1.getKey() + " ===== " + m1.getValue());
            if(m1.getKey().equals("PK")){
                m1.setValue(10000);
            }
        }
        System.out.println(lhm);
    }
}

Output:
{PK=900, Prabhas=800, NTR=300, RC=500}
900
[PK, Prabhas, NTR, RC]
[1000, 800, 300, 500]
[PK=1000, Prabhas=800, NTR=300, RC=500]
PK ===== 1000
Prabhas ===== 800
NTR ===== 300
RC ===== 500
{PK=10000, Prabhas=800, NTR=300, RC=500}

here, the insertion order is preserved.

Note: LinkedHashSet and LinkedHashMap are commonly used for developing cache-based applications.


Differences between == operator and .equals() method:
In general == operator meant for reference comparison (address comparison) whereas.equals() method meant for content comparison.
For Example

Integer I1 = new Integer(10);
Integer I2 = new Integer(10);
System.out.println(I1 == I2); // false
System.out.println(I1.equals(I2)); //true

IdentityHashMap:

  1. It is exactly same as HashMap including methods and constructors except the following difference.
  2. In the case of normal HashMap JVM will use, equals () method to identify duplicate keys, which is meant for content comparison.
  3. But int the case of IdentityHashMap JVM will use == operator to identify duplicate keys which is meant for reference comparison (address comparison)
HashMap hm = new HashMap();
Integer I1 = new Integer(10);
Integer I2 = new Integer(10);
hm.put(I1, "pawan");
hm.put(I2, "kalyan");
System.out.println(hm); //{10 = kalyan}

I1 and I2 are duplicate keys because I1.equals(I2) returns true.
If we replace HashMap with IdentityHashMap then I1 and I2 are not duplicate keys because I1 == I2 returns true.

In this case output is {10 = pawan, 10 = kalyan}


import java.util.*;
class IdentityHashMap{
    public static void main(String[] args){
        IdentityHashMap ihm = new IdentityHashMap();
        Integer I1 = new Integer(10);
        Integer I2 = new Integer(10);
        ihm.put(I1, "pawan");
        ihm.put(I2, "kalyan");
        System.out.println(ihm); //{10 = pawan, 10 = kalyan}
    }
}

WeakHashMap:

It is exactly same as HashMap except the following difference

  1. In the case pf HashMap even though the objects have doesn’t has any reference it is not eligible for garbage collection, if it is associated with HashMap i.e., HashMap dominates garbage collector.
  2. But in the case of WeakHashMap, if object doesn’t contain any references, it is eligible for Garbage collection even though object associated with WeakHashMap i.e., garbage collector dominates WeakHashMap.
import java.util.*;
class WeakHashMapDemo{
    public static void main(String[] argsthrows InterruptedException{
        HashMap<TempStringhm = new HashMap<TempString>();
        Temp t = new Temp();
        hm.put(t, "kalyan");
        System.out.println(hm);
        t = null;
        System.gc();
        Thread.sleep(5000);
        System.out.println(hm);
    }
}
class Temp{
    public String toString(){
        return "temp";
    }
    public void finalize(){
        System.out.println("finalize() method called");
    }
}

Output: {temp=kalyan}
{temp=kalyan}

In the above example Temp object is not eligible for garbage collection because it is associated with HashMap.
In this case Output is
{temp = "kalyan"}
{temp = "kalyan"}


import java.util.*;
class WeakHashMapDemo{
    public static void main(String[] argsthrows InterruptedException{
        WeakHashMap whm = new WeakHashMap();
        Temp t = new Temp();
        whm.put(t, "kalyan");
        System.out.println(whm);
        t = null;
        System.gc();
        Thread.sleep(5000);
        System.out.println(whm);
    }
}
class Temp{
    public String toString(){
        return "temp";
    }
    public void finalize(){
        System.out.println("finalize() method called");
    }
}

Output:
{temp=kalyan}
finalize() method called
{}

In the above program we replace HashMap with WeakHashMap then Temp object eligible for garbage collection.
In this case Output is
{temp = "kalyan"}
finalize() method called
{}


SortedMap(I) interface:

  1. It is the child interface of Map.
  2. If we want represent a group of objects as group of key-value pairs according to some sorting order of keys then we should go for SortedMap.
  3. Sorting is based on the key but not based on value.

SortedMap defines the following specific methods

Object firstKey()
Object lastKey()
SortedMap headMap(Object key)
SortedMap tailMap(Object key)
SortedMap subMap(Object key1, Object key2)
Comparator comparator()

{101 = A, 102 = B, 103 = C, 107 =D, 125 = E, 136 = F}

firstKey() --> 101l
astKey() --> 136
headMap(107) --> {101 = A, 103 = B, 104 = C}
tailMap(107) --> {107 = D, 125 = E, 136 = F}
subMap(103125) --> {103 = B, 104 = C, 107 = D}
comparator() --> null

TreeMap:

  1. It is one of the implementation class of Map interface. and present since JDK 1.2.
  2. TreeMap is used mainly for sorting data based on key.
  3. TreeMap implements default natural sorting order on the key using Comparable interface.
  4. For custom sorting we use Comparator.
  5. It cannot store even a single null key.
  6. TreeMap is homogeneous.
  7. NullPointerException, when we try to add null
  8. The underlined data structure is RED-BLACK Tree.
  9. Insertion order is not preserved and it is based on some sorting order of keys.
  10. Duplicate keys are not allowed but values can be duplicated.
  11. If we are depending on default natural sorting order then keys should be homogeneous and Comparable otherwise, we will get runtime exception saying ClassCastException.
  12. If we are defining our own sorting by Comparator then keys need not be homogenous and Comparable. We can take heterogenous non-Comparable objects also whether we are depending natural sorting order or customized sorting order there are nor restrictions for values. We can take heterogeneous non comparable objects also.

Null acceptance:

  1. For non-empty TreeMap if we are trying to insert an entry with null key then we will get runtime exception saying NullPointerException.
  2. For empty TreeMap as the first entry with the null key is allowed but after inserting that entry if we are trying to insert any entry then we will get runtime exception saying NullPointerException.

Note: The above null acceptance rule applicable until 1.6V only. From 1.7V null is not allowed for key. But for values we can use null any no.of times there is no restriction.


Constructors:

public TreeMap() : for default  natural sorting order
public TreeMap(Comparator c) : for customized sorting order
public TreeMap(SortedMap m) 
public TreeMap(Map m)
//Program for default natural sorting order
import java.util.*;class TreeMapDemo{
    public static void main(String[] args){
        TreeMap<IntegerStringtm = new TreeMap<IntegerString>();
        tm.put(100"kalyan");
        tm.put(103"chanukya");
        tm.put(101"hemanth");
        tm.put(104"siva");
        //tm.put("sai", "kalyan"); // ClassCastException
        //tm.put(null, "kadali") // NullPointerException
        System.out.println(tm);
    }
}

Output:
{100=kalyan, 101=hemanth, 103=chanukya, 104=siva}


//progarm for Customized sorting
import java.util.*;
class TreeMapDemo{
    public static void main(String[] args){
        TreeMap<StringIntegertm = new TreeMap<StringInteger>(new MyComparator());
        tm.put("kalyan"10);
        tm.put("chanukya"20);
        tm.put("hemanth"30);
        tm.put("siva"40);
        System.out.println(tm);
    }
}
class MyComparator implements Comparator<Object>{
    public int compare(Object obj1Object obj2){
        String s1 = obj1.toString();
        String s2 = obj2.toString();
        return s2.compareTo(s1);
    }
}

Output:
{siva=40, kalyan=10, hemanth=30, chanukya=20}


Hashtable:

  1. Hashtable is one of the implementation class of Map interface and present since JDK 1.0 [legacy class].
  2. It is also a hash-based collection, hence data structure used is Hashtable.
  3. Insertion is not preserved and it is based on hashcode of keys.
  4. Duplicate keys are not allowed and values can be allowed.
  5. Heterogeneous objects are allowed for both keys and values.
  6. Hashtable is Single threaded. i.e.., methods are synchronized and Hashtable objects is Thread safe.
  7. Hashtable cannot store even a single null key and null value otherwise we will get runtime exception saying NullPointerException.
  8. It implements Serializable, Cloneable interfaces but not RandomAccess interface.
  9. Hashtable is best choice if our frequent operation is search operation.
  10. Initial capacity is 11.
  11. Load factor or fill ratio is 75%.
  12. Hashtable is slower than HashMap. Because it is Single threaded.

There are 4 overloaded constructor presents in Hashtable

public Hashtable(Map<? extends K, ? extends V> t)
public Hashtable()
public Hashtable(int initialCapacity)
public Hashtable(int initialCapacity, float loadFactor)
import java.util.*;
class HashtableDemo{
    public static void main(String[] args){
        Hashtable h = new Hashtable();
        h.put(new Temp(5), "A");
        h.put(new Temp(2), "B");
        h.put(new Temp(6), "C");
        h.put(new Temp(15), "D");
        h.put(new Temp(23), "E");
        h.put(new Temp(16), "F");
        System.out.println(h);
    }
}
class Temp{
    int i;
    Temp(int i){
        this.i = i;
    }
    public int hashCode(){
        return i;
    }
    public String toString(){
        return i + "";
    }
}

Output:
{6=C, 16=F, 5=A, 15=D, 2=B, 23=E}

if we change hashcode method of Temp class then

hashcode
import java.util.*;
class HashtableDemo{
    public static void main(String[] args){
        Hashtable h = new Hashtable();
        h.put(new Temp(5), "A");
        h.put(new Temp(2), "B");
        h.put(new Temp(6), "C");
        h.put(new Temp(15), "D");
        h.put(new Temp(23), "E");
        h.put(new Temp(16), "F");
        System.out.println(h);
    }
}
class Temp{
    int i;
    Temp(int i){
        this.i = i;
    }
    public int hashCode(){
        return i % 9;
    }
    public String toString(){
        return i + "";
    }
}

In this case output is
{16=F, 15=D, 6=C, 23=E, 5=A, 2=B}

If we configure initial capacity as 25 then

import java.util.*;
class HashtableDemo{
    public static void main(String[] args){
        Hashtable h = new Hashtable(25);
        h.put(new Temp(5), "A");
        h.put(new Temp(2), "B");
        h.put(new Temp(6), "C");
        h.put(new Temp(15), "D");
        h.put(new Temp(23), "E");
        h.put(new Temp(16), "F");
        System.out.println(h);
    }
}
class Temp{
    int i;
    Temp(int i){
        this.i = i;
    }
    public int hashCode(){
        return i;
    }
    public String toString(){
        return i + "";
    }
}

In this case the output is
{23=E, 16=F, 15=D, 6=C, 5=A, 2=B}


Properties:

In our program if anything which changes frequently (like username, password, mobile number, mail id etc) are not recommended to hard-code in java program because if there is any change, to reflect that change recompilation, rebuild and redeploy application are required. Even sometimes server restart also required which creates a big business impact to the client.

we can overcome this problem by using properties file such type of variable things we have to configure in the properties file.
From the properties file we have to read into the java program and we can use those properties.
The main advantage of this approach is if there is a change in properties file to reflect that change just redeployment is enough which won’t create business impact to the client.

we can use java Properties object to hold properties which are coming from properties file.

In normal Map (like HashMap, Hashtable, TreeMap) Key and value can be any type but in the case of Properties Key and value should be String type.

Constructor:

public Properties()

Properties specific Methods:

String setProperty(String pname, String pvalue)

to set a new Property if the specified property aleady available then old value will be replaced with new value and returns old value

String getProperty(String pname)

to get value associated with the specified Property if the specified property not available then this method returns null.

Enumeration propertyNames()

returns all property names present in Properties object.

void load(InputStream is)

to load properties from properties file into java properties object

void store(OutputStream os, String comment)

to store properties from java properties object into properties file.

abc.properties
username = scott
password = tiger


import java.util.*;
import java.io.*;
class PropertiesDemo{
    public static void main(String[] argsthrows IOException{
        Properties p = new Properties();
        FileInputStream fis = new FileInputStream("abc.properties");
        p.load(fis);
        System.out.println(p);
        String s = p.getProperty("password");
        System.out.println(s);
        p.setProperty("email""kalyan@gmail.com");
        FileOutputStream fos = new FileOutputStream("abc.properties");
        p.store(fos, "Updated by Kadali Sai Kalyan");
    }
}  

Output:
{username = scott, password = tiger}
tiger

abc.propertiesv #Updated by Kadali Sai Kalyan
username = scott
password = tiger
email = kalyan@gmail.com

//Properties Program related to JDBC
import java.util.*;
import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
class PropertiesDemo2{
    public static void main(String[] argsthrows IOExceptionSQLException{
        Properties p = new Properties();
        FileInputStream fis = new FileInputStream("db.properties");
        p.load(fis);
        String url = p.getProperty("url");
        String user = p.getProperty("user");
        String pwd = p.getProperty("pwd");
        Connection con = DriverManager.getConnection(url, user, pwd);
    }
}

As a part of 1.6 version the following two concepts introduced in Collection framework

  1. NavigableSet
  2. NavigableMap

NavigableSet:

It is the child interface of SortedSet and it defines several methods for Navigation purposes.

NavigableSet

NavigableSet specific methods:

floor(e) returns highest element which is <= e
lower(e) returns highest element which is < e
ceiling(e) returns lowest element which is >= e
higher(e) returns lowest element which is > e
pollFirst() remove and return first element
pollLast() remove and return last element
descendingSet() returns NavigableSet in reverse order
import java.util.*;
class NavigableSetDemo{
    public static void main(String[] args){
        TreeSet<Integerts = new TreeSet<Integer>();
        ts.add(1000);
        ts.add(2000);
        ts.add(3000);
        ts.add(4000);
        ts.add(5000);
        System.out.println(ts); //[1000, 2000, 3000, 4000, 5000]
        System.out.println(ts.ceiling(2000)); //2000
        System.out.println(ts.higher(2000)); //3000
        System.out.println(ts.floor(3000)); //3000
        System.out.println(ts.lower(3000)); //2000
        System.out.println(ts.pollFirst()); //1000
        System.out.println(ts.pollLast()); //5000
        System.out.println(ts.descendingSet()); //[4000, 3000, 2000]
        System.out.println(ts); //[2000, 3000, 4000]
    }
}

Output:
[1000, 2000, 3000, 4000, 5000]
2000
3000
3000
2000
1000
5000
[4000, 3000, 2000]
[2000, 3000, 4000]


NavigableMap:

NavigableMap is the child interface of SortedMap.
It defines several methods for Navigation purposes.

NavigableMap

NavigableMap is the child interface of SortedMap.
it defines several methods for Navigation purposes.


NavigableMap specific methods :

floorKey(e) returns highest key which is <= e
lowerKey(e) returns highest key which is < e
ceilingKey(e) returns lowest key which is >= e
higherKey(e) returns lowest key which is > e
pollFirstEntry() remove and return first entry
pollLastEntry() remove and return last entry
descendingMap() returns NavigableMap in reverse order
import java.util.*;
class NavigableMapDemo{
    public static void main(String[] args){
        TreeSet<IntegerStringts = new TreeSet<IntegerString>();
        ts.put(103"Kalyan");
        ts.put(105"Chanukya");
        ts.put(101"Hemanth");
        ts.put(104"Siva");
        ts.put(102"Pasupathi");
        System.out.println(ts);
        System.out.println(ts.ceilingKey(103));
        System.out.println(ts.higherKey(105));
        System.out.println(ts.floorKey(104));
        System.out.println(ts.lowerKey(104));
        System.out.println(ts.pollFirstEntry());
        System.out.println(ts.pollLastEntry());
        System.out.println(ts.descendingMap());
        System.out.println(ts);
     }
}