HashMap in Java is most commonly used where we want to store the data in key-value pairs.

HashMap in Java internally follows the HashTable implementation. It extends the AbstractMap class which is implemented from the Map interface.

HashMap in Java

Following are the constructors of the HasMap.

  1. public HashMap(): This is the most commonly used constructor to create an object. This will create an empty HashMap with default capacity as 16 and load factor as 0.75
  1. public HashMap(int initialCapacity): If we want to initiate capacity at the time of creation then we can use this constructor method. Default load factor will be 0.75 (Load Factor is used to figure out when HashMap will be rehashed and bucket size will be increased).
  1. public HashMap(int initialCapacity, float loadFactor):  Here we can give default capacity and load factor at the time of object creation.
  1. public HashMap(Map<? extends K, ? extends V> m): This will create a new map with a given specified map. Default capacity and load factor will be the same as the given specified map.

Following is the simple example for java HashMap using the above 4 construction methods.

Java Code
import java.util.HashMap;
class Test {
public static void main(String[] args) {
// By Using public HashMap()
HashMap<Integer,String> map1 = new HashMap<>();
map1.put(5, “ABCD”);
map1.put(2, “EFGH”);
System.out.println(“Map1: ” + map1);

// By using public HashMap(int initialCapacity)
HashMap<Integer,String> map2 = new HashMap<>(5);
map2.put(1, “LMNO”);
map2.put(5, “PQRS”);
System.out.println(“Map2: ” + map2);

// By using public HashMap(int initialCapacity, float loadFactor)
HashMap<Integer,String> map3 = new HashMap<>(5, 0.5f);
map3.put(12, “EXOP”);
map3.put(13, “LBTS”);
System.out.println(“Map3: ” + map3);

// By using public HashMap(Map m)
HashMap<Integer,String> map4 = new HashMap<>(map2);
map4.put(2,”KAHS”);
System.out.println(“Map4: ” + map4);
}
}
Output:
Map1: {2=EFGH, 5=ABCD}
Map2: {1=LMNO, 5=PQRS}
Map3: {12=EXOP, 13=LBTS}
Map4: {1=LMNO, 5=PQRS, 2=KAHS}

How does HashMap internally work?

  1. Hash map is stored in key-value pairs. It’s inner class Node is used to store the mappings
  2. HashMap uses key hashcode and equals methods to get and put operations.
  3. When we call the put method of HashMap key hashcode of is used to determine the bucket of the hashmap.
  4. If anything is already present in that key then the equals method is used on the key. If it returns true then that key is overridden else new mapping is created.
  5. If no key is present in the bucket then new mapping is inserted into it.
  6. For the get method again key hashcode method is used to identify the bucket. Once it’s identified entries are traversed to find the required entry using hashcode and equals method. If a match is found then value is returned else null is returned.

Following are the methods used in HashMap. (Note that K for Key and V for Value):

  1. V get(Object key): This returns the value for specified key, or null if no mapping for key is found.
  2. V getOrDefault(Object key, V defaultValue): This returns the value for specified key, or returns defaultValue if no mapping for key is found.
  3. V put(K key, V value): To associate given value to the specified key.
  4. void putAll(Map<? extends K,? extends V> m): To copy all the entries from the specified map.
  5. V putIfAbsent(K key, V value): This will check if the specified key is already associated with any value, if not then entry will be added else this method will return the current value. 
Java Code
import java.util.HashMap;
class Test {
public static void main(String[] args) {
HashMap<Integer,String> map1 = new HashMap<>();
map1.put(5, “ABCD”);
map1.put(2, “EFGH”);

System.out.println(“get(2): ” + map1.get(2));
System.out.println(“get(3): ” + map1.get(3));
System.out.println(“getOrDefault(): ” + map1.getOrDefault(3, “DVSB”));

HashMap<Integer,String> map2 = new HashMap<>(5);
map2.put(1, “LMNO”);
map2.put(12, “EXOP”);
map2.put(13, “LBTS”);

map1.putAll(map2);
System.out.println(“putIfAbsent(12, KSFH): ” + map1.putIfAbsent(12, “KSFH”));
System.out.println(“putIfAbsent(16, SPGK): ” + map1.putIfAbsent(12, “SPGK”));

System.out.println(“Final Map1: ” + map1);
}
}
Output:
get(2): EFGH
get(3): null
getOrDefault(): DVSB
putIfAbsent(12, KSFH): EXOP
putIfAbsent(16, SPGK): EXOP
Final Map1: {1=LMNO, 2=EFGH, 5=ABCD, 12=EXOP, 13=LBTS}

  1. V replace(K key, V value): This will replace the entry for the specified key with a given value and returns the old value.
  2. boolean replace(K key, V oldValue, V newValue): Replaces the entry for the specified key only if currently mapped value matches with specified oldValue, It will be replaced with newValue.
  3. void replaceAll(BiFunction<? super K,? super V,? extends V> function):  This will replace all the entries values with a given new Value until all entries have been processed or the action throws an exception.
Java Code
import java.util.HashMap;
class Test {
public static void main(String[] args) {
HashMap<Integer,String> map1 = new HashMap<>();
map1.put(5, “ABCD”);
map1.put(2, “EFGH”);
map1.put(1, “LMNO”);
map1.put(7, “PQRS”);
System.out.println(“Original Map: ” + map1);
System.out.println(“replace(2, VJKM): ” + map1.replace(2, “VJKM”));
System.out.println(“replace(1, LMNO): ” + map1.replace(1, “LMNO”, “RMSG”));

System.out.println(“Updated Map : ” + map1);
// replaceAll(BiFunction<K, V> function) appending ABC at the end
map1.replaceAll((key, oldValue) -> oldValue + “ABC”);
System.out.println(“Final Map: ” + map1);
}
}
Output:
Original Map: {1=LMNO, 2=EFGH, 5=ABCD, 7=PQRS}
replace(2, VJKM): EFGH
replace(1, LMNO): true
Updated Map : {1=RMSG, 2=VJKM, 5=ABCD, 7=PQRS}
Final Map: {1=RMSGABC, 2=VJKMABC, 5=ABCDABC, 7=PQRSABC}

  1. boolean containsKey(Object key): This will check if a specified key is present in the HashMap entries.
  2. boolean containsValue(Object value): This will check if a specified value is present in the HashMap entries.
  3. int size(): This will return the size of the HashMap.
  4. V remove(Object key): This will remove the entry if specified key if present. This method will return the value which is removed.
  5. boolean remove(Object key, Object value): This will remove the entry if specified key is present and is mapped to specified value.
  6. void clear(): This will delete all the entries from the HashMap.
  7. boolean isEmpty(): This will check if the map has any entry or not.
Java Code
import java.util.HashMap;
class Test {
public static void main(String[] args) {
HashMap<Integer,String> map1 = new HashMap<>();
map1.put(5, “ABCD”);
map1.put(2, “EFGH”);
map1.put(1, “LMNO”);
map1.put(7, “PQRS”);
System.out.println(“Original Map: ” + map1);
System.out.println(“containsKey(2): ” + map1.containsKey(2));
System.out.println(“containsValue(LMNO): ” + map1.containsValue(“LMNO”));
System.out.println(“size: ” + map1.size());
System.out.println(“remove(2): ” + map1.remove(2));
System.out.println(“remove(1, LMNO): ” + map1.remove(1, “LMNO”));
System.out.println(“Updated Map: ” + map1);

map1.clear();
System.out.println(“isEmpty: ” + map1.isEmpty());
System.out.println(“Final Map: ” + map1);
}
}
Output:
Original Map: {1=LMNO, 2=EFGH, 5=ABCD, 7=PQRS}
containsKey(2): true
containsValue(LMNO): true
size: 4
remove(2): EFGH
remove(1, LMNO): true
Updated Map: {5=ABCD, 7=PQRS}
isEmpty: true
Final Map: {}

  1. Set<Map.Entry<K,V>> entrySet(): Returns a Set view of the mappings present in the map.
  2. void forEach(BiConsumer<? super K,? super V> action): Performs the given action for each entry in the map until all entries have been processed or the action throws an exception.
  3. Set<K> keySet(): Returns a Set of the keys present in the map.
  4. Collection<V> values(): Returns a Collection of the values present in the map.
Java Code
import java.util.HashMap;
import java.util.Set;
import java.util.Map;
import java.util.Collection;
class Test {
public static void main(String[] args) {
HashMap<Integer,String> map1 = new HashMap<>();
map1.put(5, “ABCD”);
map1.put(2, “EFGH”);
map1.put(1, “LMNO”);
map1.put(7, “PQRS”);
System.out.println(“Original Map: ” + map1);
Set<Map.Entry<Integer, String>> set = map1.entrySet();
System.out.println(“set: ” + set);

map1.forEach((key, value) -> {
System.out.println(“Key: “+ key + “, Value: ” + value);
});
System.out.println();

Set<Integer> keySet = map1.keySet();
System.out.println(“keySet: ” + keySet);

Collection<String> values = map1.values();
System.out.println(“values: ” + values);
}
}
Output:
Original Map: {1=LMNO, 2=EFGH, 5=ABCD, 7=PQRS}
set: [1=LMNO, 2=EFGH, 5=ABCD, 7=PQRS]
Key: 1, Value: LMNO
Key: 2, Value: EFGH
Key: 5, Value: ABCD
Key: 7, Value: PQRS

keySet: [1, 2, 5, 7]
values: [LMNO, EFGH, ABCD, PQRS]

  1. Object clone(): Returns a shallow copy of this HashMap instance: the keys and values themselves are not cloned.
  2. V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction): If the specified key is not already associated with a value or is associated with null, associate it with the given non-null value.
Java Code
import java.util.HashMap;
class Test {
public static void main(String[] args) {
HashMap<Integer,String> map1 = new HashMap<>();
map1.put(5, “ABCD”);
map1.put(2, “EFGH”);
map1.put(1, “LMNO”);
map1.put(7, “PQRS”);
System.out.println(“Map1: ” + map1);

HashMap<Integer, String> clonMap = (HashMap<Integer, String>) map1.clone();
System.out.println(“Clonned Map: ” + clonMap);

HashMap<Integer,String> map2 = new HashMap<>();
map2.put(2, “EFGH”);
map2.put(5, “JKRM”);
map2.put(6, “SGSK”);
System.out.println(“Map2: ” + map2);

// Here values for key 5 is will be merged with both values key 5 is alredy present and has different value, key 6 will be directly merged
map2.forEach((key, value) ->
map1.merge(key,value,(v1, v2) ->
v1.equalsIgnoreCase(v2) ? v1 : v1 + “, ” + v2));
System.out.println(“Final Map1: ” + map1);
}
}
Output:
Map1: {1=LMNO, 2=EFGH, 5=ABCD, 7=PQRS}
Clonned Map: {1=LMNO, 2=EFGH, 5=ABCD, 7=PQRS}
Map2: {2=EFGH, 5=JKRM, 6=SGSK}
Final Map1: {1=LMNO, 2=EFGH, 5=ABCD, JKRM, 6=SGSK, 7=PQRS}

  1. V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction): Attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping).
  2. V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction): If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.
  3. V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction): If the value for the specified key is present and non-null, attempts to compute a new mapping given the key and its current mapped value.
Java Code
import java.util.HashMap;
class Test {
public static void main(String[] args) {
HashMap<Integer,String> map1 = new HashMap<>();
map1.put(5, “ABCD”);
map1.put(2, “EFGH”);
map1.put(1, “LMNO”);
map1.put(7, “PQRS”);
System.out.println(“Map1: ” + map1);
map1.compute(7, (key, val) -> val.concat(” & TUVW”));
// Entry will be added
map1.computeIfAbsent(3, key -> “VJKL”);
// No change since key is present
map1.computeIfAbsent(1, key -> “LAJS”);

// Entry will be added
map1.computeIfPresent(5, (key, val) -> val.concat(” & RMSG”));
// No change since key is not present
map1.computeIfPresent(4, (key, val) -> val.concat(” & BJSK”));

System.out.println(“Final Map1: ” + map1);
}
}
Output:
Map1: {1=LMNO, 2=EFGH, 5=ABCD, 7=PQRS}
Final Map1: {1=LMNO, 2=EFGH, 3=VJKL, 5=ABCD & RMSG, 7=PQRS & TUVW}

Following are the important points about HashMap:

  1. The underlying data structure is HashTable.
  2. Insertion order is not preserved in the HashMap and based on the hashcode of keys.
  3. Duplicate keys not allowed. Values can be duplicated.
  4. Heterogeneous objects are allowed for both key and value.
  5. null is allowed for key (only once).
  6. null is allowed for values (any no. of times).
  7. HashMap implements Serializable and Cloneable interfaces but not RandomAccess.
  8. Best choice if our frequent operation is search operation.
  9. HashMap is Non synchronized.

-A blog by Shwetali Khambe

Related Posts