July 06, 2024

#Collections: Part 1- A Guide to Map in Java

What is a Map in Java?

In Java, a Map is an interface that represents a collection of key-value pairs where each key is unique within the Map, and it maps to exactly one value. It is part of the Java Collections Framework and provides methods to manipulate and retrieve data based on the keys.

Here are some common implementations of Map:
  • HashMap: Stores key-value pairs in a hash table, allowing O(1) average time complexity for insertion and lookup operations.
  • TreeMap: Maintains keys in a sorted order (natural ordering or by a specified comparator), allowing O(log n) time complexity for insertion and lookup.
  • LinkedHashMap: Maintains insertion order of keys, which means it preserves the order in which keys were inserted.
Methods of Map:
  • void clear( ): Removes all key/value pairs from the invoking map.
  • boolean containsKey(Object k): Returns true if the invoking map contains k as a key. Otherwise, returns false.
  • boolean containsValue(Object v): Returns true if the map contains v as a value. Otherwise, returns false.
  • Set entrySet( ): Returns a Set that contains the entries in the map. The set contains objects of type Map.Entry. This method provides a set view of the invoking map.
  • boolean equals(Object obj): Returns true if obj is a Map and contains the same entries. Otherwise, returns false.
  • Object get(Object k): Returns the value associated with the key k.
  • int hashCode( ): Returns the hash code for the invoking map.
  • boolean isEmpty( ): Returns true if the invoking map is empty. Otherwise, returns false.
  • Set keySet( ): Returns a Set that contains the keys in the invoking map. This method provides a set-view of the keys in the invoking map.
  • Object put(Object k, Object v): Puts an entry in the invoking map, overwriting any previous value associated with the key. The key and value are k and v, respectively. Returns null if the key does not already exist. Otherwise, the previous value linked to the key is returned.
  • void putAll(Map m): Puts all the entries from m into this map.
  • Object remove(Object k): Removes the entry whose key equals k.
  • Collection values( ): Returns a collection containing the values in the map. This method provides a collection view of the values in the map.

Why Map interface does not extend the Collection interface in the Java Collections Framework?

The map interface is not compatible with the Collection interface. 

Since Map requires key as well as value, e.g if we want to add key-value pair then we will use put(Object key , Object value). So there are two parameters required to add an element to the HashMap object. 

In the Collection interface add(Object o) has only one parameter. The other reason is, Map supports valueSet, keySet as well as other appropriate methods which have just different views from the Collection interface.

What are common exceptions thrown by operations of Java Map?

A NullPointerException is thrown if an attempt is made to use a null object and null is not allowed in the map.

Hashtable would always throw a NullPointerException for either null keys or values. Whereas, a HashMap would be happy with both null keys and values.

TreeMap would accept null values, but would throw a NullPointerException with null keys. However, if the very first pair had a null key, then it accepted it happily. If we created the TreeMap with a Comparator that worked with null, then the tree would accept a null key.

WeakHashMap would accept null keys, but would never remove that entry again.

Several methods throw a NoSuchElementException when no items exist in the invoking map. This exception can be thrown by methods like Iterator.next() when there are no more elements to iterate over, typically in situations where the Map is empty or the iterator has reached the end of the collection.

A ClassCastException is thrown when an object is incompatible with the elements in a map. e.g: Using a key that does not implement Comparable in a TreeMap that requires keys to be comparable. Or trying to cast an object retrieved from Map to an incompatible type.

An UnsupportedOperationException is thrown when an attempt is made to change an unmodifiable map. e.g trying to modify an unmodifiable Map. Or calling remove() on an Iterator obtained from keySet() or entrySet() views.

ConcurrentModificationException typically occurs when the Map is modified structurally (such as adding or removing elements) while iterating over it using an iterator. It indicates that another thread has modified the map concurrently during iteration, causing inconsistency.

Why String, Integer and other wrapper classes are considered good keys?

The string is the most frequently used key as well because String is immutable and final, and overrides equals and hashcode() method. Other wrapper class also shares similar properties. Immutability is required, in order to prevent changes on fields used to calculate hashCode() because if key object returns different hashCode during insertion and retrieval than it won't be possible to get an object from HashMap.

Immutability is best as it offers other advantages as well like thread safety, if you can keep your hashCode the same by only making certain fields final, then you go for that as well. Since the equals() and hashCode() method is used during the retrieval of value objects from HashMap, it's important that the key object correctly overrides these methods and follows contact. If an unequal object returns a different hashcode then the chances of collision will be less which subsequently improve the performance of HashMap.

Can we use any custom object as a key in HashMap?

Yes, we can use any Object as a key in Java HashMap provided it follows equals and hashCode contract and its hashCode should not vary once the object is inserted into Map. If the custom object is Immutable then this will be already taken care of because you can not change it once created.

-K Himaanshu Shuklaa..

No comments:

Post a Comment