Showing posts with label Java map. Show all posts
Showing posts with label Java map. Show all posts

Saturday, June 1, 2024

ConcurrentHashMap in Java With Examples

ConcurrentHashMap in Java is introduced as another thread-safe alternative to Hashtable (or explicitly synchronizing the map using synchronizedMap method) from Java 5. ConcurrentHashMap class extends AbstractMap class and implements ConcurrentMap interface through which it provides thread safety and atomicity guarantees.

Why another Map

First thing that comes to mind is why another map when we already have a HashMap or HashTable. If you need to use a Map like structure with in a multi-threaded environment with thread safety you can use a Hashtable or a synchronized HashMap by using Collections.synchronizedMap() method. Then what unique does ConcurrentHashMap in Java offer?

Problem with Hashtable or synchronized Map is that all of its methods are synchronized on a common lock thus only a single thread can access it at any given time, even for read operations, making these data structures slower. ConcurrentHashMap is designed to provide better performance while providing thread safety too.


How performance is improved in ConcurrentHashMap

ConcurrentHashMap in Java is also a hash based map like HashMap, how it differs is the locking strategy used by it. Unlike HashTable (or synchronized HashMap) it doesn't synchronize every method on a common lock. ConcurrentHashMap uses separate lock for separate buckets thus locking only a portion of the Map.

If you have idea about the internal implementation of the HashMap you must be knowing that by default there are 16 buckets. Same concept is used in ConcurrentHashMap and by default there are 16 buckets and also separate locks for separate buckets. So the default concurrency level is 16.

Since there are 16 buckets having separate locks of their own which effectively means at any given time 16 threads can operate on the map concurrently, provided all these threads are operating on separate buckets. So you see how ConcurrentHashMap provides better performance by locking only the portion of the map rather than blocking the whole map resulting in greater shared access.

For locking any of the bucket independently of the other buckets the first node in the bucket is locked by using synchronized keyword. Note that before Java 8, implementation of Java ConcurrentHashMap used to have Segment array with with each segment having its own lock which has been changed from Java 8. Now the first node in the bucket itself is locked using the node's own builtin synchronized monitors.

ConcurrentHashMap Internal implementation in Java
ConcurrentHashMap implementation in Java

Further performance improvement

Performance of Java ConcurrentHashMap is further improved by providing read access concurrently without any blocking. Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations which may mean that retrieval operations may not fetch the current/in-progress value (Which is one drawback). Memory visibility for the read operations is ensured by volatile reads. You can see in the ConcurrentHashMap code that the val and next fields of Node are volatile.

Also for aggregate operations such as putAll and clear which works on the whole map, concurrent retrievals may reflect insertion or removal of only some entries (another drawback of separate locking). Because read operations are not blocking but some of the writes (which are on the same bucket) may still be blocking.

Constructors in Java ConcurrentHashMap

There are five constructors in the ConcurrentHashMap class-

  • ConcurrentHashMap()- Creates a new, empty map with the default initial table size (16).
  • ConcurrentHashMap(int initialCapacity)- Creates a new, empty map with an initial table size accommodating the specified number of elements without the need to dynamically resize.
  • ConcurrentHashMap(int initialCapacity, float loadFactor)- Creates a new, empty map with an initial table size based on the given number of elements (initialCapacity) and initial table density (loadFactor).
  • ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel)- Creates a new, empty map with an initial table size based on the given number of elements (initialCapacity), table density (loadFactor), and number of concurrently updating threads (concurrencyLevel).
  • ConcurrentHashMap​(Map<? extends K,? extends V> m)- Creates a new map with the same mappings as the given map.

Java ConcurrentHashMap example

At this juncture let's see a simple example where a ConcurrentHashMap is created and (key, value) pairs are added to it. Then getting the collection view of the Map it is iterated to display the stored keys and values.

public class CHMDemo {
  public static void main(String[] args) {
    // Creating ConcurrentHashMap
    Map<String, String> cityTemperatureMap = new ConcurrentHashMap<String, String>();
    
    // Storing elements
    cityTemperatureMap.put("Delhi", "24");
    cityTemperatureMap.put("Mumbai", "32");
    //cityTemperatureMap.put(null, "26");
    cityTemperatureMap.put("Chennai", "35");
    cityTemperatureMap.put("Bangalore", "22" );
    
    for (Map.Entry<String, String> e : cityTemperatureMap.entrySet()) {
      System.out.println(e.getKey() + " = " + e.getValue());
    }
  }
}

Null is not allowed in ConcurrentHashMap

Though HashMap allows one null as key but ConcurrentHashMap doesn't allow null as key. In the previous example you can uncomment the line which has null key. While trying to execute the program it will throw null pointer exception.

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class CHMDemo {
  public static void main(String[] args) {
    // Creating ConcurrentHashMap
    Map cityTemperatureMap = new ConcurrentHashMap();
    
    // Storing elements
    cityTemperatureMap.put("Delhi", "24");
    cityTemperatureMap.put("Mumbai", "32");
    // Adding null key
    cityTemperatureMap.put(null, "26");
    cityTemperatureMap.put("Chennai", "35");
    cityTemperatureMap.put("Bangalore", "22" );
    
    for (Map.Entry e : cityTemperatureMap.entrySet()) {
      System.out.println(e.getKey() + " = " + e.getValue());
    }
  }
}
Exception in thread "main" java.lang.NullPointerException
 at java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011)
 at java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1006)
 at org.netjs.prog.CHMDemo.main(CHMDemo.java:16)

Atomic operations in ConcurrentHashMap

ConcurrentHashMap in Java provides a lot of atomic methods, let's see it with an example how these atomic methods help. Note that from Java 8 many new atomic methods are added.

Suppose you have a word Map that counts the frequency of every word where key is the word and count is the value, in a multi-threaded environment, even if ConcurrentHashMap is used, there may be a problem as described in the code snippet.

public class CHMAtomicDemo {
  public static void main(String[] args) {
    ConcurrentHashMap<String, Integer> wordMap = new ConcurrentHashMap<>();
    ..
    ..
    // Suppose one thread is interrupted after this line and 
    // another thread starts execution
    Integer prevValue = wordMap.get(word); 
    
    Integer newValue = (prevValue == null ? 1 : prevValue + 1);
    // Here the value may not be correct after the execution of 
    // both threads
    wordMap.put(word, newValue);  
  }
}

To avoid these kind of problems you can use atomic method, one of the atomic method is compute which can be used here.

wordMap.compute(word, (k,v)-> v == null ? 1 : v + 1);

If you see the general structure of the Compute method

compute(K key, BiFunction<? super K,? super V,? extendsV> remappingFunction)
Here BiFunction functional interface is used which can be implemented as a lambda expression.

So here rather than having these lines-

Integer prevValue = wordMap.get(word); 
Integer newValue = (prevValue == null ? 1 : prevValue + 1);
wordMap.put(word, newValue);
you can have only this line
wordMap.compute(word, (k,v)-> v == null ? 1 : v + 1);

The entire method invocation is performed atomically. Some attempted update operations on this map by other threads may be blocked while computation is in progress.

There are several other atomic operations like computeIfAbsent, computeIfPresent, merge, putIfAbsent.

Fail-safe iterator in ConcurrentHashMap

Iterator returned by the Java ConcurrentHashMap is fail-safe which means it will not throw ConcurrentModificationException. It can be seen in the example code where a new (key, value) pair is added while the map is iterated, still it doesn't throw ConcurrentModificationException.

public class CHMDemo {
  public static void main(String[] args) {
    // Creating ConcurrentHashMap
    Map<String, String> cityTemperatureMap = new ConcurrentHashMap<String, String>();
    
    // Storing elements
    cityTemperatureMap.put("Delhi", "24");
    cityTemperatureMap.put("Mumbai", "32");
    cityTemperatureMap.put("Chennai", "35");
    cityTemperatureMap.put("Bangalore", "22" );
    
    Iterator<String> iterator = cityTemperatureMap.keySet().iterator();   
    while (iterator.hasNext()){
      System.out.println(cityTemperatureMap.get(iterator.next()));
      // adding new value, it won't throw error
      cityTemperatureMap.put("Kolkata", "34");        
    }
  }
}

Output

24
35
34
32
22

According to the JavaDocs- The view's iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

When is ConcurrentHashMap a better choice

ConcurrentHashMap is a better choice when there are more reads than writes. As mentioned above retrieval operations are non-blocking so many concurrent threads can read without any performance problem. If there are more writes and that too many threads operating on the same segment then the threads will block which will deteriorate the performance.

Points to note

  • ConcurrentHashMap in Java is also a hash based map like HashMap, but ConcurrentHashMap is thread safe.
  • In ConcurrentHashMap thread safety is ensured by having separate locks for separate buckets, resulting in better performance.
  • In ConcurrentHashMap class, by default the bucket size is 16 and the concurrency level is also 16.
  • Null keys are not allowed in Java ConcurrentHashMap.
  • Iterator provided by the ConcurrentHashMap is fail-safe, which means it will not throw ConcurrentModificationException.
  • Retrieval operations (like get) don't block so may overlap with update operations (including put and remove).

That's all for this topic ConcurrentHashMap in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between HashMap And ConcurrentHashMap in Java
  2. CopyOnWriteArrayList in Java With Examples
  3. How HashMap Works Internally in Java
  4. Java CountDownLatch With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. How to Iterate a HashMap of ArrayLists of String in Java
  2. How to Sort HashSet in Java
  3. Difference Between Comparable and Comparator in Java
  4. Try-With-Resources in Java With Examples
  5. static reference to the non-static method or field error
  6. Race Condition in Java Multi-Threading
  7. Angular Reactive Form Validation Example
  8. Spring MVC Radiobutton And Radiobuttons Form Tag Example

Sunday, March 24, 2024

ConcurrentSkipListMap in Java With Examples

ConcurrentSkipListMap in Java is a scalable concurrent map which implements ConcurrentNavigableMap interface. Though concurrent collections like ConcurrentHashMap and CopyOnWriteArrayList were added in Java 1.5, ConcurrentSkipListMap and the similar set implementation ConcurrentSkipListSet were added in Java 1.6.


ConcurrentNavigableMap interface

ConcurrentNavigableMap interface in Java is a ConcurrentMap supporting NavigableMap operations, and recursively so for its navigable sub-maps. It was added in Java 1.6.

ConcurrentNavigableMap interface in turn extends NavigableMap interface. Where NavigableMap is a SortedMap extended with navigation methods returning the closest matches for given search targets. Methods lowerEntry, floorEntry, ceilingEntry, and higherEntry return Map.Entry objects associated with keys respectively less than, less than or equal, greater than or equal, and greater than a given key, returning null if there is no such key. Similarly, methods lowerKey, floorKey, ceilingKey, and higherKey return only the associated keys. All of these methods are designed for locating, not traversing entries.

ConcurrentSkipListMap in Java

Since ConcurrentSkipListMap implements ConcurrentNavigableMap, it is a sorted map just like TreeMap in Java (Which also implements NavigableMap interface), with added functionality of being concurrent.

ConcurrentSkipListMap is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used.

Java ConcurrentSkipListMap constructors

ConcurrentSkipListMap class provides four constructors, which are as follows-

  • ConcurrentSkipListMap()- Constructs a new, empty map, sorted according to the natural ordering of the keys.
  • ConcurrentSkipListMap(Comparator<? super K> comparator)- Constructs a new, empty map, sorted according to the specified comparator.
  • ConcurrentSkipListMap​(Map<? extends K,? extends V> m)- Constructs a new map containing the same mappings as the given map, sorted according to the natural ordering of the keys.
  • ConcurrentSkipListMap​(SortedMap<K,? extends V> m)- Constructs a new map containing the same mappings and using the same ordering as the specified sorted map.

ConcurrentSkipListMap class in Java implements a concurrent variant of SkipLists data structure providing expected average log(n) time cost for the containsKey, get, put and remove operations and their variants. Insertion, removal, update, and access operations safely execute concurrently by multiple threads.

All Map.Entry pairs returned by methods in ConcurrentSkipListMap class and its views represent snapshots of mappings at the time they were produced.

No nulls in ConcurrentSkipListMap

Note that ConcurrentSkipListMap class in Java does not permit the use of null keys or values because some null return values cannot be reliably distinguished from the absence of elements.

Java example creating ConcurrentSkipListMap

Let's see an example where we add some values in a ConcurrentSkipListMap and in the output it can be seen that it is sorted based on the natural ordering of its keys. In this example keys are Strings and for String natural ordering is ascending alphabetical order. So when you loop the map you'll see it is sorted based on the keys.

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;

public class CSMDemo {
  public static void main(String[] args) {
    ConcurrentNavigableMap<String, String> cityMap = new ConcurrentSkipListMap<String, String>();
    cityMap.put("ND", "New Delhi");
    cityMap.put("MU", "Mumbai");
    cityMap.put("CH", "Chennai");
    cityMap.put("HD", "Hyderabad");
    Set<Map.Entry<String, String>> citySet = cityMap.entrySet();
    citySet.forEach((m)->System.out.println("key " + m.getKey() 
              + " value " + m.getValue()));
  }
}

Output

key CH value Chennai
key HD value Hyderabad
key MU value Mumbai
key ND value New Delhi

Here it can be seen that ConcurrentNavigableMap is sorted on the keys.

ConcurrentSkipListMap with Comparator

If you want sorting to be done in reverse order then you can pass a Comparator as a parameter when constructing a ConcurrentSkipListMap.

public class CSMDemo {
  public static void main(String[] args) {
    // With Comparator
    ConcurrentNavigableMap<String, String> cityMap = new ConcurrentSkipListMap<String, String>((String s1, String s2) -> s1.compareTo(s2));
    cityMap.put("ND", "New Delhi");
    cityMap.put("MU", "Mumbai");
    cityMap.put("CH", "Chennai");
    cityMap.put("HD", "Hyderabad");
    Set<Map.Entry<String, String>> citySet = cityMap.entrySet();
    citySet.forEach((m)->System.out.println("key " + m.getKey() 
             + " value " + m.getValue()));
  }
}

Output

key CH value Chennai
key HD value Hyderabad
key MU value Mumbai
key ND value New Delhi

Here it can be seen that elements in the ConcurrentNavigableMap are now sorted in reversed order.

Navigational methods in Java ConcurrentSkipListMap

As already mentioned ConcurrentSkipListMap in Java implements ConcurrentNavigableMap interface so it has many navigation methods returning the closest matches for given search targets. Let's see some of them in example code.

  • descendingKeySet()- Returns a reverse order NavigableSet view of the keys contained in this map.
  • floorEntry(K key)- Returns a key-value mapping associated with the greatest key less than or equal to the given key, or null if there is no such key.
  • headMap(K toKey)- Returns a view of the portion of this map whose keys are strictly less than toKey.
  • higherKey(K key)- Returns the least key strictly greater than the given key, or null if there is no such key.
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Set;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;

public class CSMDemo {
  public static void main(String[] args) {
    ConcurrentNavigableMap<String, String> cityMap = new ConcurrentSkipListMap<String, String>();
    cityMap.put("ND", "New Delhi");
    cityMap.put("MU", "Mumbai");
    cityMap.put("CH", "Chennai");
    cityMap.put("HD", "Hyderabad");
    System.out.println("---- Traversing the map-----");
    Set<Map.Entry<String, String>> citySet = cityMap.entrySet();
    // using for-each loop in Java 8
    citySet.forEach((m)->System.out.println("key " + m.getKey() + 
            " value " + m.getValue()));
        
    NavigableSet<String> reverseKeys = cityMap.descendingKeySet();
    // using iterator
    Iterator<String> itr = reverseKeys.iterator();
    System.out.println("---- Map keys in reverse order-----");
    while(itr.hasNext()){
      System.out.println("Key " + itr.next());
    }
        
    System.out.println("---- Floor entry-----");
    
    Map.Entry<String, String> tempMap = cityMap.floorEntry("II");
    System.out.println(tempMap);
        
    System.out.println("---- Head Map-----");
    ConcurrentNavigableMap<String, String> map = cityMap.headMap("MU");
    Set<Map.Entry<String, String>> set = map.entrySet();
    // using for-each loop in Java 8
    set.forEach((m)->System.out.println("key " + m.getKey() + 
                " value " + m.getValue()));
    
    System.out.println("---- Higher entry-----");
        
    tempMap = cityMap.higherEntry("II");
    System.out.println(tempMap);
  }
}

Output

---- Traversing the map-----
key CH value Chennai
key HD value Hyderabad
key MU value Mumbai
key ND value New Delhi
---- Map keys in reverse order-----
Key ND
Key MU
Key HD
Key CH
---- Floor entry-----
HD=Hyderabad
---- Head Map-----
key CH value Chennai
key HD value Hyderabad
---- Higher entry-----
MU=Mumbai

DescendingKeySet returns the keys in reverse order.

floorEntry() method returns the greatest key less than or equal to the given key. Here key is provided as "II" if you see greatest key less than or equal to "II" is "HD". Note here that key provided should not be a key already present in the Map ("II" is not a key present in the Map).

That's all for this topic ConcurrentSkipListMap in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentHashMap in Java With Examples
  2. Java CyclicBarrier With Examples
  3. Java ArrayBlockingQueue With Examples
  4. How to Sort Elements in Different Order in TreeSet
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. Java ReentrantLock With Examples
  2. Difference between HashMap and ConcurrentHashMap in Java
  3. How to Iterate a HashMap of ArrayLists of String in Java
  4. HashMap Vs LinkedHashMap Vs TreeMap in Java
  5. Method Reference in Java
  6. Difference Between Abstract Class And Interface in Java
  7. super Keyword in Java With Examples
  8. Creating Custom Exception Class in Java

Tuesday, January 9, 2024

How HashMap Works Internally in Java

In this Java tutorial you'll learn how HashMap works internally in Java, which is also a favorite Java Collections interview question. Note that code snippets used here are from JDK 17.

There are four things you should know about HashMap before going into internal working of HashMap in Java-

  • HashMap works on the principal of hashing.
  • Map.Entry interface- This interface gives a map entry (key-value pair). HashMap in Java stores both key and value object, in bucket, as an object of Node class which implements this nested interface Map.Entry. Read more about Map.Entry interface here.
  • hashCode()- HashMap provides put(key, value) method for storing and get(key) method for retrieving values from HashMap. When put() method is used to store (Key, Value) pair, HashMap implementation calls hashcode on Key object to calculate a hash that is used to find a bucket where Entry object will be stored.
    When get() method is used to retrieve value, again key object (passed with the get() method) is used to calculate a hash which is then used to find a bucket where that particular key is stored.
  • equals()- equals() method is used to compare objects for equality. In case of HashMap key object is used for comparison, also using equals() method Map knows how to handle hashing collision (hashing collision means more than one key having the same hash value, thus assigned to the same bucket). In that case objects are stored in a linked list, refer figure for more clarity.
    Where hashCode() method helps in finding the bucket where that key is stored, equals() method helps in finding the right key as there may be more than one key-value pair stored in a single bucket.

** Bucket term used here is actually an index of array, that array is called table in HashMap implementation. Thus table[0] is referred as bucket0, table[1] as bucket1 and so on.


How elements are stored internally in Java HashMap

HassMap class in Java internally uses an array called table of type Node to store the elements which is defined in the HashMap class as-

transient Node<K,V>[] table;
Node is defined as a static class with in a Hashmap.
static class Node<K,V> implements Map.Entry<K,V> {
  final int hash;
  final K key;
  V value;
  Node<K,V> next;
  ..
  ..  
}

As you can see for each element four things are stored in the following fields-

  • hash- For storing Hashcode calculated using the key.
  • key- For holding key of the element.
  • value- For storing value of the element.
  • next- To store reference to the next node when a bucket has more than one element and a linkedlist is formed with in a bucket to store elements.

Following image shows how Node(key-value pair) objects are stored internally in table array of the HashMap class.

HashMap internal implementation in Java

Importance of hashCode() and equals() method in HashMap

How important it is to have a proper hash code and equals method can be seen through the help of the following program, explanation of this example will also help in understanding the working of HashMap's put()method (next section).

public class HashMapTest {
  public static void main(String[] args) {
    Map <Key, String> cityMap = new HashMap<Key, String>();
    cityMap.put(new Key(1, "NY"),"New York City" );
    cityMap.put(new Key(2, "ND"), "New Delhi");
    cityMap.put(new Key(3, "NW"), "Newark");
    cityMap.put(new Key(4, "NP"), "Newport");

    System.out.println("size before iteration " + cityMap.size());
    Iterator <Key> itr = cityMap.keySet().iterator();
    while (itr.hasNext()){
      System.out.println(cityMap.get(itr.next()));     
    }
    System.out.println("size after iteration " + cityMap.size());    
  }
}

// This class' object is used as key
// in the HashMap
class Key{
  int index;
  String Name;
  Key(int index, String Name){
    this.index = index;
    this.Name = Name;
  }
 
  @Override
  // A very bad implementation of hashcode
  // done here for illustrative purpose only 
  public int hashCode(){
    return 5;
  }
 
  @Override
  // A very bad implementation of equals
  // done here for illustrative purpose only 
  public boolean equals(Object obj){
    return true;
  }
}

Output

size before iteration 1
Newport
size after iteration 1

Refer Overriding hashCode() and equals() method in Java to know more about hashCode() and equals() methods.

How put() method of Java HashMap works internally

Lets get through the above example to see what is happening, this will also help in understanding how put() method of HashMap works internally.

Notice that I am inserting 4 values in the HashMap, still in the output it says size is 1 and iterating the map gives me the last inserted entry. Why is that? Answer lies in, how hashCode() and equals() method are implemented for the key Class. Have a look at the hashCode() method of the class Key which always returns "5" and the equals() method which is always returning "true".

When a value is put into HashMap it calculates a hash using key object and for that it uses the hashCode() method of the key object class (or its parent class). Based on the calculated hash value HashMap implementation decides which bucket should store the particular Entry object.

In my code the hashCode() method of the key class always returns "5". This effectively means, calculated hash value, is same for all the entries inserted in the HashMap. Thus all the entries are stored in the same bucket.

HashMap implementation uses equals() method to see if the key is equal to any of the already inserted keys (Recall that there may be more than one entry in the same bucket). Note that, with in a bucket key-value pair entries (Entry objects) are stored in a linked-list (Refer figure for more clarity). In case hash is same, but equals() returns false (which essentially means more than one key having the same hash or hash collision) Entry objects are stored, with in the same bucket, in a linked-list.

In my code, I am always returning true for equals() method so the HashMap implementation "thinks" that the keys are equal and overwrites the value. So, in a way using hashCode() and equals() I have "tricked" HashMap implementation to think that all the keys (even though different) are same, thus overwriting the values.

In a nutshell there are three steps in the internal implementation of HashMap put() method-

  • Using hashCode() method, hash value will be calculated. In which bucket particular entry will be stored is ascertained using that hash.
  • equals() method is used to find if such a key already exists in that bucket, if not found then a new node is created with the map entry and stored within the same bucket. A linked-list is used to store those nodes.
  • If equals() method returns true, it means that the key already exists in the bucket. In that case, the new value will overwrite the old value for the matched key.

How Java HashMap get() method works internally

As we already know how Entry objects are stored in a bucket and what happens in the case of Hash Collision it is easy to understand what happens when key object is passed in the get() method of the HashMap to retrieve a value.

Using the key (passed in the get() method) hash value will be calculated to determine the bucket where that Entry object is stored, in case there are more than one Entry object with in the same bucket (stored as a linked-list) equals() method will be used to find out the correct key. As soon as the matching key is found get() method will return the value object stored in the Entry object.

When null Key is inserted in a HashMap

HashMap in Java also allows null as key, though there can only be one null key in HashMap. While storing the Entry object HashMap implementation checks if the key is null, in case key is null, it is always mapped to bucket 0, as hash is not calculated for null keys.

HashMap implementation changes in Java 8

Though HashMap implementation in Java provides constant time performance O(1) for get() and put() methods but that is in the ideal case when the Hash function distributes the objects evenly among the buckets.

But the performance may worsen in the case hashCode() used is not proper and there are lots of hash collisions. As we know now that in case of hash collision entry objects are stored as a node in a linked-list and equals() method is used to compare keys. That comparison to find the correct key with in a linked-list is a linear operation so in a worst case scenario the complexity becomes O(n).

To address this issue in Java 8 hash elements use balanced trees instead of linked lists after a certain threshold is reached. Which means HashMap starts with storing Entry objects in linked list but after the number of items in a hash becomes larger than a certain threshold, the hash changes from using a linked list to a balanced tree, this improves the worst case performance from O(n) to O(log n).

Points to note-

  • HashMap works on the principal of hashing.
  • HashMap in Java uses the hashCode() method to calculate a hash value. Hash value is calculated using the key object. This hash value is used to find the correct bucket where Entry object will be stored.
  • HashMap uses the equals() method to find the correct key whose value is to be retrieved in case of get() and to find if that key already exists or not in case of put().
  • With in the internal implementation of HashMap hashing collision means more than one key having the same hash value, in that case Entry objects are stored as a linked-list with in a same bucket.
  • With in a bucket values are stored as Entry objects which contain both key and value.
  • In Java 8 hash elements use balanced trees instead of linked lists after a certain threshold is reached while storing values. This improves the worst case performance from O(n) to O(log n).

That's all for this topic How HashMap Works Internally in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How ArrayList Works Internally in Java
  2. How LinkedList Class Works Internally in Java
  3. How HashSet Works Internally in Java
  4. How to Loop Through a Map in Java
  5. ConcurrentHashMap in Java With Examples

You may also like-

  1. strictfp in Java
  2. Constructor Chaining in Java
  3. Interface Static Methods in Java
  4. Method reference in Java 8
  5. Difference Between Checked And Unchecked Exceptions in Java
  6. Try-With-Resources in Java With Examples
  7. Inter-thread Communication Using wait(), notify() And notifyAll() in Java
  8. Count Number of Times Each Character Appears in a String Java Program

Wednesday, January 18, 2023

HashMap Vs LinkedHashMap Vs TreeMap in Java

Though HashMap, LinkedHashMap and TreeMap all are implementations of the Map interface and share some traits like

But there are certain differences too related to how elements are ordered, performance etc. So it is very important to know these differences among HashMap, LinkedHashMap and TreeMap in Java as it will help you to make an informed choice about which Map implementation should be used to meet the requirement.

Differences among HashMap, LinkedHashMap and TreeMap in Java

  1. First and most important difference is related to Ordering of the elements.
    HashMap makes no guarantees as to the order of the map.
    LinkedHashMap maintains the insertion order or access order (based on the constructor) of the elements. Which means if we iterate a LinkedHashMap we'll get the keys in the order in which they were inserted in the Map or the order in which its entries were last accessed, from least-recently accessed to most-recently.
    TreeMap stores objects in sorted order. The elements in TreeMap are ordered according to the natural ordering of its keys or a Comparator can be provided at map creation time to provide custom ordering of its keys.

  2. Another difference is related to allowing null as key or value.
    HashMap as well as LinkedHashMap allows one null as key, multiple values may be null though.
    TreeMap does not allow null as key. Any attempt to add null in a TreeMap will result in a NullPointerException. Values may be null.

  3. For HashMap and LinkedHashMap comparison of the elements is done using equals() method.
    As Example in get method for the passed key k, if this map contains a mapping from a key k to a value v such that (key==null ? k==null : key.equals(k)), then this method returns v; otherwise it returns null.
    TreeMap does the comparison of the keys using the compareTo (or compare) method, depending on whether sorting is done using Comparable or Comparator.
    As Example in get method for the passed key k, if this map contains a mapping from a key k to a value v such that key compares equal to k according to the map's ordering, then this method returns v; otherwise it returns null.

  4. HashMap class extends AbstractMap and implements Map interface.
    LinkedHashMap class extends HashMap and implements Map interface.
    TreeMap class extends AbstractMap and implements NavigableMap interface.

  5. HashMap stores elements in a bucket which actually is an index of the array which means the backing data structure for the HashMap is an array where bucket0 means index[0], bucket1 means index[1] of that array.
    LinkedHashMap extends HashMap and uses the same internal implementation as HashMap. Apart from that it also maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering.
    TreeMap is a Red-Black tree based NavigableMap implementation.

  6. Performance wise HashMap provides constant time performance O(1) for get() and put() method but that is in the ideal case when the Hash function distributes the objects evenly among the buckets. In worst case when equals() and HashCode() implementation is not good it may even become O(n).
    LinkedHashMap also provides constant time performance O(1) for get() and put() method but in general a little slower than the HashMap as it has to maintain a doubly linked list.
    TreeMap provides guaranteed log(n) time cost for the containsKey, get, put and remove operations.

That's all for this topic HashMap Vs LinkedHashMap Vs TreeMap in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between HashMap And Hashtable in Java
  2. How to Loop Through a Map in Java
  3. LinkedHashMap in Java With Examples
  4. HashSet Vs LinkedHashSet Vs TreeSet in Java
  5. Java Collections Interview Questions And Answers

You may also like-

  1. How to Sort Elements in Different Order in TreeSet
  2. How to Sort ArrayList of Custom Objects in Java
  3. Deadlock in Java Multi-Threading
  4. Difference Between sleep And wait in Java Multi-Threading
  5. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  6. Java Pass by Value or Pass by Reference
  7. Serialization Proxy Pattern in Java
  8. Creating Custom Exception Class in Java

Saturday, December 24, 2022

Difference Between HashMap And Hashtable in Java

Though both Hashtable and HashMap in Java have some similarities like storing elements as a (key, value) pair and using hashing technique to store elements. From Java V1.2, Hashtable class was also retrofitted to implement the Map interface, making it a member of the Java Collections Framework. Still there are some differences in these two data structures. In this post we'll see those differences between HashMap and Hashtable in Java.

HashMap Vs Hashtable in Java

  • HashMap is not synchronized where as Hashtable is synchronized. Which essentially means that Hashtable is inherently thread safe where as HashMap is not. If we need to synchronize a HashMap then that has to be done explicitly by calling the following method.
    Map m = Collections.synchronizedMap(hashMap);
    
  • HashMap allows one null value as a key and any number of null values.
    Hashtable does not allow null values either as key or as value.
  • For traversing a HashMap an iterator can be used. That iterator is fail-fast and throws ConcurrentModificationException if any other Thread modifies the map structurally by adding or removing any element except Iterator's own remove() method.
    For traversing a Hashtable either an iterator or Enumerator can be used. Here again the iterator is fail-fast where as Enumerator is fail-safe.
    public class HashTableDemo {
      public static void main(String[] args) {
        Hashtable<String, Integer> numbers = new Hashtable<String, Integer>();
        numbers.put("one", 1);
        numbers.put("two", 2);
        numbers.put("three", 3);
        // Using enumerator
        for (Enumeration<String> e = numbers.keys(); e.hasMoreElements();){
          System.out.println(e.nextElement());
          numbers.put("four", 4);
        }
    
        // Using iterator
        Iterator<String> itr =  numbers.keySet().iterator();
        while (itr.hasNext()){
          System.out.println(numbers.get(itr.next()));
          numbers.put("five", 5);
        }  
      }
    }
    

    Output

    two
    one
    three
    four
    2
    Exception in thread "main" java.util.ConcurrentModificationException
     at java.util.Hashtable$Enumerator.next(Unknown Source)
     at org.netjs.prog.HashTableDemo.main(HashTableDemo.java:22)
    

    Here it can be seen that while enumerating a Hashtable if a new value is added (i.e. Hashtable is structurally modified) that doesn't throw any exception. Whereas, if a new value is added, while iterating it throws a ConcurrentModificationException.

  • Performance wise HashMap is faster than the Hashtable reason being HashMap is not synchronized.

That's all for this topic Difference Between HashMap And Hashtable in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How HashMap Works Internally in Java
  2. LinkedHashMap in Java With Examples
  3. TreeMap in Java With Examples
  4. Difference Between HashMap And ConcurrentHashMap in Java
  5. Java Collections Interview Questions And Answers

You may also like-

  1. static Reference to The Non-static Method or Field Error
  2. Abstraction in Java
  3. ThreadLocal class in Java With Examples
  4. Setter-based dependency injection in Spring
  5. How to Remove Duplicate Elements From an ArrayList in Java
  6. EnumSet in Java With Examples
  7. Java BlockingQueue With Examples
  8. @FunctionalInterface Annotation in Java

Friday, October 28, 2022

Java Map size() With Examples

If you want to know how many key-value pair are there in a Map you can use size() method which returns the number of key-value mappings in the map.

Syntax of the size() method is

int size()

Method doesn't take any parameters.

Method returns an int value denoting the number of key-value mappings in the map

size() method Java example

Here we have a HashMap with some key, value pair added. Using size() method we'll get the current size of the map.

import java.util.HashMap;
import java.util.Map;

public class SizeMapDemo {
  public static void main(String[] args) {
    Map<String, String> cityMap = new HashMap<String, String>();
    // Adding elements
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Beijing");
    cityMap.put("5", "Berlin");
    
    int sizeOfMap = cityMap.size();
    System.out.println("Number of entries in the Map: " + sizeOfMap);
  }
}

Output

Number of entries in the Map: 5

That's all for this topic Java Map size() With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. removeIf() Method in Java Collection With Examples
  2. Java Map putIfAbsent() With Examples
  3. Java Map replace() With Examples
  4. Difference Between ArrayList And LinkedList in Java
  5. Java Collections Interview Questions And Answers

You may also like-

  1. How to Sort Elements in Different Order in TreeSet
  2. CopyOnWriteArrayList in Java With Examples
  3. Type Wrapper Classes in Java
  4. Why Class Name And File Name Should be Same in Java
  5. Convert String to Char Array in Java
  6. Python First Program - Hello World
  7. ApplicationContextAware And BeanNameAware Interfaces in Spring Framework
  8. What is SafeMode in Hadoop

Thursday, October 27, 2022

removeIf() Method in Java Collection With Examples

In this post we'll see how to use removeIf() method to remove elements from the Collection that satisfy the given condition. The removeIf() method is included in java.util.Collection interface in Java 8. Since it is part of Collection interface so you can use it with Collections like ArrayList, HashSet that implements Collection interface. To use it with HashMap you will have to get a collection view of the Map, since Map doesn't implement Collection interface.


Java removeIf() method syntax

boolean removeIf(Predicate<? super E> filter)

Parameter passed to this method is of type Predicate functional interface, which can be implemented as a boolean-valued function with one argument.

Method returns true if any elements were removed.

Removing elements from ArrayList using removeIf() method

In this example we'll have a list of cities and we'll remove elements from this ArrayList using removeIf() method. In passed Predicate if the condition holds true for any of the elements, then that element is removed from the list.

import java.util.ArrayList;
import java.util.List;

public class RemoveIf {

  public static void main(String[] args) {
    List<String> cityList = new ArrayList<String>();
    cityList.add("Delhi");
    cityList.add("Mumbai");
    cityList.add("Kolkata");
    cityList.add("Hyderabad");
    cityList.add("Bangalore");
    cityList.add("Mumbai");
    System.out.println("*** List Initially ***");
    System.out.println(cityList);
    cityList.removeIf(p -> p.equalsIgnoreCase("Hyderabad") || 
          p.equalsIgnoreCase("Bangalore"));
    System.out.println("After Removal " + cityList);
  }
}

Output

*** List Initially ***
[Delhi, Mumbai, Kolkata, Hyderabad, Bangalore, Mumbai]
After Removal [Delhi, Mumbai, Kolkata, Mumbai]

Removing elements from HashSet using removeIf() method

You can use removeIf() method with HashSet also to remove elements from the Set based on the passed condition. In the given example condition is to remove cities having name of length more than 6.

import java.util.HashSet;
import java.util.Set;

public class RemoveIf {

  public static void main(String[] args) {
    // creating a HashSet
    Set<String> citySet = new HashSet<String>();
    // Adding elements
    citySet.add("London");        
    citySet.add("Tokyo");
    citySet.add("New Delhi");
    citySet.add("Beijing");
    citySet.add("Nairobi");
    System.out.println("*** Set Initially ***");
    System.out.println(citySet);
    
    // Remove all cities having length more than 6
    citySet.removeIf(e -> e.length() > 6);
    System.out.println("After Removal " + citySet);
  }
}

Output

*** Set Initially ***
[Beijing, New Delhi, Nairobi, Tokyo, London]
After Removal [Tokyo, London]

Removing elements from HashMap using removeIf() method

To use removeIf() method with a Map you have to get Collection view of a Map. After getting the Collection view of a Map removeIf() method can be used.

import java.util.HashMap;
import java.util.Map;


public class RemoveIf {

  public static void main(String[] args) {
    Map<String, String> cityMap = new HashMap<String, String>();
    // Adding elements
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Beijing");
    cityMap.put("5", "Berlin");

    System.out.println("*** Map Initially ***");
    System.out.println(cityMap);
      
    // Use entrySet to get Set view of all Map entries. 
    // Remove entry from Map based on the condition for value.
    cityMap.entrySet().removeIf(entry -> entry.getValue().equals("Beijing"));
    System.out.println("*** Map After removal ***");
    System.out.println(cityMap);
  }
}

Output

*** Map Initially ***
{1=New York City, 2=New Delhi, 3=Mumbai, 4=Beijing, 5=Berlin}
*** Map After removal ***
{1=New York City, 2=New Delhi, 3=Mumbai, 5=Berlin}

That's all for this topic removeIf() Method in Java Collection With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How to Remove Entry From HashMap in Java
  2. How to Remove Elements From an ArrayList in Java
  3. How to Remove Duplicate Elements From an ArrayList in Java
  4. Java Map replace() With Examples
  5. HashSet Vs LinkedHashSet Vs TreeSet in Java

You may also like-

  1. Difference Between Comparable and Comparator in Java
  2. CopyOnWriteArraySet in Java With Examples
  3. Switch Expressions in Java 12
  4. Java Nested Class And Inner Class
  5. Reading File in Java Using Files.lines And Files.newBufferedReader
  6. Angular Cross Component Communication Using Subject Observable
  7. Angular HttpClient - Set Response Type as Text
  8. Spring Web MVC Tutorial

Friday, October 21, 2022

Java Map replace() With Examples

The replace() method in java.util.Map is added in Java 8. The replace() method replaces the value associated with the specified key only if the key is already mapped to some value. That's how replace() method differs from put() method, if a key is passed to the put() method that doesn't already exist in the Map then it will add the entry (key, value pair) to the Map.

Replace method in Java Map

There are two overloaded replace methods

1. V replace(K key, V value)

Replaces the entry for the specified key only if it is currently mapped to some value.

Paramters are-

  • key- The specified key for which value has to be replaced
  • value- New value to be associated with the specified key

Method returns the previous value if the key is mapped to a value. Returns null if key is not associated with any value, returns null if associated values is null for the key.

2. boolean replace(K key, V oldValue, V newValue)

Replaces the oldValue with newValue for the specified key only if the key is currently mapped to the oldValue.

  • key- Specified key for which value has to be changed
  • oldValue- Value expected to be associated with the specified key
  • newValue- Value that replaces the oldValue

Method returns true if the value was replaced, false otherwise.

replace() method Java examples

In this example we'll use replace(K key, V value) variant.

import java.util.HashMap;
import java.util.Map;

public class ReplaceDemo {
  public static void main(String[] args) {
    // Setting up a HashMap
    Map<String, String> cityMap = new HashMap<String, String>();
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Berlin");
    
    System.out.println("*** Map Initially ***");
    System.out.println(cityMap);
    String prevValue = cityMap.replace("3", "Chennai");
    System.out.println("Value that is replaced " + prevValue);
    
    prevValue = cityMap.replace("5", "Mumbai");
    System.out.println("Value that is replaced " + prevValue);
    
    System.out.println("*** Map After replacement ***");
    System.out.println(cityMap);
  }
}

Output

*** Map Initially ***
{1=New York City, 2=New Delhi, 3=Mumbai, 4=Berlin}
Value that is replaced Mumbai
Value that is replaced null
*** Map After replacement ***
{1=New York City, 2=New Delhi, 3=Chennai, 4=Berlin}

When "3" is passed as key in the replace() method the passed value replaces the previous value. In this case replace() method returns previous value associated with the key.

When "5" is passed as key there is no change in the Map as the key is not present in the HashMap. In this case replace() method returns null.

In this example we'll use replace(K key, V oldValue, V newValue) variant.

public class ReplaceDemo {

  public static void main(String[] args) {
    // Setting up a HashMap
    Map<String, String> cityMap = new HashMap<String, String>();
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Berlin");
    
    System.out.println("*** Map Initially ***");
    System.out.println(cityMap);
    boolean isReplaced = cityMap.replace("3", "Mumbai", "Chennai");
    System.out.println("Is value replaced " + isReplaced);
    
    isReplaced = cityMap.replace("4", "Mumbai", "Madrid");
    System.out.println("Is value replaced " + isReplaced);
    
    System.out.println("*** Map After replacement ***");
    System.out.println(cityMap);
  }
}

Output

*** Map Initially ***
{1=New York City, 2=New Delhi, 3=Mumbai, 4=Berlin}
Is value replaced true
Is value replaced false
*** Map After replacement ***
{1=New York City, 2=New Delhi, 3=Chennai, 4=Berlin}

First time value is replaced because key "3" was mapped with "Mumbai" initially. In this case replace() method returns true.

Second time there is no replacement because key "4" is there but it is not associated with "Mumbai". In this case replace() method returns false.

That's all for this topic Java Map replace() With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How to Remove Entry From HashMap in Java
  2. Java Map putIfAbsent() With Examples
  3. How HashMap Works Internally in Java
  4. HashSet Vs LinkedHashSet Vs TreeSet in Java
  5. Difference Between Comparable and Comparator in Java

You may also like-

  1. How to Convert Array to ArrayList in Java
  2. Java Phaser With Examples
  3. Java Abstract Class and Abstract Method
  4. java.lang.UnsupportedClassVersionError - Resolving UnsupportedClassVersionError in Java
  5. Convert double to int in Java
  6. Spring Setter Based Dependency Injection
  7. BeanFactoryAware Interface in Spring Framework
  8. FormGroup in Angular With Examples

Wednesday, October 19, 2022

How to Remove Entry From HashMap in Java

In this post we'll see how to remove an entry (key, value pair) from Map. Options you have are as given below-

  1. Using remove method- remove(Object key) provided by Map. See Example
  2. Using another remove method variant- remove(Object key, Object value) provided by Map. See Example
  3. Using remove() method provided by iterator. See Example
  4. Using removeIf() method. See Example

So, let's see when to use which method and why.

Removing entry from HashMap using remove(Object key) method

If you know the key for the entry which has to be removed, it is convenient to use remove(Object key) method rather than iterating the Map and then use iterator.remove() to remove the entry. This method returns the value which was associated with the removed key or null if the map contained no mapping for the key.

Here is an example with the map of cities where we'll try to remove Map.entry by passing one of the key.

import java.util.HashMap;
import java.util.Map;

public class RemoveEntryDemo {

  public static void main(String[] args) {
    // Setting up a HashMap
    Map<String, String> cityMap = new HashMap<String, String>();
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Berlin");
    
    System.out.println("*** Map Initially ***");
    System.out.println(cityMap);
      
    cityMap.remove("4");
    System.out.println("*** Map After removal ***");
    System.out.println(cityMap);
  }
}

Output

*** Map Initially ***
{1=New York City, 2=New Delhi, 3=Mumbai, 4=Berlin}
*** Map After removal ***
{1=New York City, 2=New Delhi, 3=Mumbai}

As you can see the entry with key as "4" is removed from the HashMap.

Removing entry from HashMap using remove(Object key, Object value) method

This is another overloaded remove() method in Map which makes removing an entry more restrictive. This method removes the entry for the specified key only if it is currently mapped to the specified value.

public class RemoveEntryDemo {

  public static void main(String[] args) {
    // Setting up a HashMap
    Map<String, String> cityMap = new HashMap<String, String>();
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Berlin");
    
    System.out.println("*** Map Initially ***");
    System.out.println(cityMap);
      
    cityMap.remove("4", "Berlin");
    System.out.println("*** Map After removal ***");
    System.out.println(cityMap);
  }
}

Output

{1=New York City, 2=New Delhi, 3=Mumbai, 4=Berlin}
*** Map After removal ***
{1=New York City, 2=New Delhi, 3=Mumbai}

Since the passed key "4" is mapped to the specified value "Berlin" so entry is removed.

If you give a value that is not mapped with any key no entry is removed. For example, if you try cityMap.remove("4", "London"); HashMap will have no change.

Using iterator's remove() method

If you don't know the key before hand and iterating the Map to find the entry that has to be removed then using remove() method of the Iterator is a safe bet.

If you have to iterate a HashMap then you need to get a collection view of the Map. The iterators returned by HashMap's "collection view methods" are fail-fast: if the Map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. Here is an example where remove() method of the Map is used to remove an entry (Structural modification) rather than using the remove() method of the iterator. This operation results in ConcurrentModificationException being thrown.

public class RemoveEntryDemo {

  public static void main(String[] args) {
    // Setting up a HashMap
    Map<String, String> cityMap = new HashMap<String, String>();
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Berlin");
    
    System.out.println("*** Map Initially ***");
    System.out.println(cityMap);
    Iterator<Entry<String, String>> itr = cityMap.entrySet().iterator();
    while(itr.hasNext()) {
      String key = itr.next().getKey();
      if(key.equals("2")) {
        cityMap.remove(key);
      }
    }

    System.out.println("*** Map After removal ***");
    System.out.println(cityMap);
  }
}

Output

*** Map Initially ***
{1=New York City, 2=New Delhi, 3=Mumbai, 4=Berlin}
Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1597)
	at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1630)
	at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1628)
	at com.netjstech.collections.RemoveEntryDemo.main(RemoveEntryDemo.java:23)

Correct way to remove an entry from a Map while iterating it is to use iterator's remove() method.

public class RemoveEntryDemo {

  public static void main(String[] args) {
    // Setting up a HashMap
    Map<String, String> cityMap = new HashMap<String, String>();
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Berlin");
    
    System.out.println("*** Map Initially ***");
    System.out.println(cityMap);
    Iterator<Entry<String, String>> itr = cityMap.entrySet().iterator();
    while(itr.hasNext()) {
      if(itr.next().getKey().equals("2")) {
        itr.remove();
      }
    }

    System.out.println("*** Map After removal ***");
    System.out.println(cityMap);
  }
}

Output

*** Map Initially ***
{1=New York City, 2=New Delhi, 3=Mumbai, 4=Berlin}
*** Map After removal ***
{1=New York City, 3=Mumbai, 4=Berlin}

Using removeIf() method

removeIf() method is in Collection interface, since Map doesn't implement Collection so removeIf() method is not directly accessible in HashMap but after getting the Collection view of a Map removeIf() method can be used.

public class RemoveEntryDemo {

  public static void main(String[] args) {
    // Setting up a HashMap
    Map<String, String> cityMap = new HashMap<String, String>();
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Berlin");
    
    System.out.println("*** Map Initially ***");
    System.out.println(cityMap);
    cityMap.entrySet().removeIf(entry -> entry.getKey().equals("2"));


    System.out.println("*** Map After removal ***");
    System.out.println(cityMap);
  }
}

Output

*** Map Initially ***
{1=New York City, 2=New Delhi, 3=Mumbai, 4=Berlin}
*** Map After removal ***
{1=New York City, 3=Mumbai, 4=Berlin}
If you have a collection view of values then
cityMap.values().removeIf(v -> v.equals("Mumbai"));
Same way if you have a collection view of keys
cityMap.keySet().removeIf(k -> k.equals("2"));

That's all for this topic How to Remove Entry From HashMap in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java Map putIfAbsent() With Examples
  2. Java Map containsValue() - Check if Value Exists in Map
  3. How to Sort a HashMap in Java
  4. How LinkedList Class Works Internally in Java
  5. How to Sort Elements in Different Order in TreeSet

You may also like-

  1. Difference Between HashMap And ConcurrentHashMap in Java
  2. CompletableFuture in Java With Examples
  3. super Keyword in Java With Examples
  4. strictfp in Java
  5. Angular Application Bootstrap Process
  6. ServiceLocatorFactoryBean in Spring
  7. Spring @Async @EnableAsync Annotations - Asynchronous Method Support
  8. Python Conditional Statement - if, elif, else Statements

Monday, October 17, 2022

Java Map putIfAbsent() With Examples

The putIfAbsent() method in java.util.Map is added in Java 8 and it puts a new value for the specified key only if the specified key is not already associated with a value in the Map or is mapped to null. There is also a computeIfAbsent() method in Java which also puts a value if specified key is not already associated with a value but with computeIfAbsent() value is computed using the given mapping function.

Syntax of the putIfAbsent () method is as given below.

V putIfAbsent(K key, V value)

Parameters are as-

  • key- key with which the specified value is to be associated
  • value- value to be associated with the specified key

Method returns the previous value if the specified key is already associated with the value.

Returns null if specified key is not already present in the Map, which actually means key is absent and the method is inserting the given key, value pair in the Map. It may also mean that the key is present but associated with null value.

The default implementation for putIfAbsent() is as given below. As you can see just by using single method putIfAbsent() you get the logic of checking whether the key is already present or not in the map and putting the value in case key is not there (or associated value is null).

 V v = map.get(key);
 if (v == null)
     v = map.put(key, value);
 return v;

putIfAbsent () Java examples

1. In the first example we'll have a map of cities and we'll try to insert a new city with a key which already exists in the HashMap.

import java.util.HashMap;
import java.util.Map;

public class PutIfAbsentDemo {

  public static void main(String[] args) {
    // Setting up a HashMap
    Map<String, String> cityMap = new HashMap<String, String>();
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Berlin");
    String val = cityMap.putIfAbsent("4", "London");
    System.out.println("Value is- " + val);   
    System.out.println(cityMap);
  }
}

Output

Value is- Berlin
{1=New York City, 2=New Delhi, 3=Mumbai, 4=Berlin}

Since key already exists and mapped with a value in the HashMap so putIfAbsent() method won't replace the previous value with new value for the same key. Also notice the return value of the method which is the value associated with the specified key.

2. In this example we'll try to insert a new city with a key which is not already there in the Map.

public class PutIfAbsentDemo {

  public static void main(String[] args) {
    // Setting up a HashMap
    Map<String, String> cityMap = new HashMap<String, String>();
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", "Berlin");
    String val = cityMap.putIfAbsent("5", "London");
    System.out.println("Value is- " + val);   
    System.out.println(cityMap);
  }
}

Output

Value is- null
{1=New York City, 2=New Delhi, 3=Mumbai, 4=Berlin, 5=London}

Since key is not there in the Map so a new entry is added to the HashMap. Also notice the return value of the putifAbsent() method which is null this time because there was no mapping for the key.

3. In this example we'll take the scenario when the key exists in the HashMap but mapped with null.

public class PutIfAbsentDemo {

  public static void main(String[] args) {
    // Setting up a HashMap
    Map<String, String> cityMap = new HashMap<String, String>();
    cityMap.put("1","New York City" );
    cityMap.put("2", "New Delhi");
    cityMap.put("3", "Mumbai");
    cityMap.put("4", null);
    String val = cityMap.putIfAbsent("4", "London");
    System.out.println("Value is- " + val);   
    System.out.println(cityMap);
  }
}

Output

Value is- null
{1=New York City, 2=New Delhi, 3=Mumbai, 4=London}

Since the key is mapped to null so putIfAbsent() method associates the key with a new value.

That's all for this topic Java Map putIfAbsent() With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java Map merge() With Examples
  2. Java Map getOrDefault() Method With Examples
  3. Map.Entry Interface in Java
  4. EnumSet in Java With Examples
  5. Java Collections Interview Questions And Answers

You may also like-

  1. Java StampedLock With Examples
  2. CopyOnWriteArraySet in Java With Examples
  3. Garbage Collection in Java
  4. Difference Between Checked And Unchecked Exceptions in Java
  5. How to Read Excel File in Java Using Apache POI
  6. Spring Boot StandAlone (Console Based) Application Example
  7. Spring MVC Exception Handling - @ExceptionHandler And @ControllerAdvice Example
  8. Angular @HostBinding Decorator With Examples