Java ☕️ Maps 🗺 on the Kotlin.

Curious how Kotlin resolve the Java platform’s map?

Most of the Kotlin developers are migrated from the Java environment, they are pretty well versed with uses-cases and application of Collection Framework in the Java platform, but applying the same knowledge in a Kotlin codebase isn’t guaranteed to work always. You could end up with a spaghetti codebase base having a long trailing function and making hacks to achieve a functionality that could easily be solved using Kotlin’s standard functions easily. Kotlin stdlib which offers generic interfaces, classes, and functions for creating, populating, and managing Collections of any type.

In Today’s article, we will try to understand how Kotlin catered to Java Maps in his its colors. Disclaimer This article is specific to Kotlin JVM as collection implementation varies with the platform you are targeting in Kotlin. I’m Chetan Gupta, I do tech stuff, don’t forget to checkout from personal blogs from AndroidBites, without any delays, Let’s get started.

Note:
This Post is given `Silver award` in Reddit at r/android_devs,
thanks community for supporting my blogs and it really motivating me!

Map 🗺

It’s a collection of key-value pairs, mainly focus on retrieving a value against the key.

kotlin map signature
  • Keys are unique and similar to the index of an array.
  • A map can hold only one value against a key.
  • The map is a read-only collection but for the sake of understanding, I will be addressing it as Immutable*.
  • The modifying part is supported using Mutable maps, discussed later in the article.
  • Map<K, V> is not an inheritor of the Collection Interface, but it’s the part of the Kotlin Collection type.

Entries 🚪

An entry represents a key/value pair in a map.

kotlin entry signature

A map contains a Set<Entry<K,V>> type entries to store its key/value, since its a Set, the uniqueness is enforced into the map entries.

kotlin map definition

Even though an entry is representing a key-value pair in a map, there is no way to directly create a map using it i.e if you can see possible ways we can create a map :

Kotlin map creation stdlib function

There is no function which creates a map using the Entry, if you check Entry Interface from docs, you will see

kotlin entry to pair

Entry can be converted to Pair but not to a map directly (like a SingletonMap), even if you focus on entries in the map which are Set<Entry<K, V>> there is no function that converts a Set<Entry<String, Int>> into Map.

Iterable <Pair> to Map

Since there is no direct support of entries to map, hence we can conclude that it’s used only as an internal implementation of key/value entries, but for the outside world it has to implement using Pair type.

Entries to pair to map

Since we are creating Maps using Pair , let’s focus on what is it?

Pair 👥

A Pair represents a generic pair of two values. It is a separate data structure, which is not a part of the Collection Framework. It can be used for any purpose.

Pair definition

It isn’t necessary that the first and the second the element of the Pair holds any relation with each other, but Entry’s first element i.e key has a relation with the second element i.e value.

But since Entry can’t be used to create maps directly there was no logical point in having a standard extension that converts Pair into Map.Entry type, thus stdlib doesn’t have Pair.toEntry() function.

There is a discussion in the form regarding it but it goes nowhere.

Since Pair are used to create Map, the extension below supports that Idea.

Pairs to Map

Map is the base Interface for AbstractMap and MutableMap, so all the core ADT functions such as get , put , contains , containsKey , isEmpty , size etc are implemented in it.

Check out the complete list of base functions from docs :

mapOf 👷‍♂️

If you have focused on Map signature interface Map<K, out V>, it’s an interface, i.e it needs to have an implementing class.

In Kotlin, we have three functions for implementing maps and all of them are resolved using different implementations of Map.

map creation standard function
map resolved by empty map
Map resolved by Singleton map
Map resolved by linked hashmap

So if you are working with a map which has more than one entry, is highly likely to be resolved by using an implementation of LinkedHashMap. We will know about it later in the article.

TLDR ☕️

Maps :

  • Maps are read-only key/value pair of collection
  • They use Entry to represent the internal state of key/value
  • You use Pairs to create a map
  • Maps implementation varies but is mostly resolved with LinkedHashMap

Mutable Map 📝

As the name suggests, it’s a mutable implementation of a Map. It’s a modifiable version of the map.

Signature for mutableMaps

Similar to Map, MutableMap has MutableEntry that represents a key/value pair but unlike Entry it is mutable :

MutableEntry signature

Entries in the mutableMap is now a MutableSet :

Entries in the mutable map are mutable set

Since Map was immutable*(read-only), there was no mutable function such as :

mutable map operations

All the functions available in the Map are overridden using mutable type variants, You can check them out from docs :

Mutable Pair? 🤔

Since you now see everything is implemented in Mutable Maps using mutable types, means Pair which are used to construct mutable map should have a mutable implementation as well, isn’t it?

Logically your thinking is right but only if you look it in terms of Collection, Pairs are not part of collection.

The immutability and Mutability collections concept is introduced to provide a read-only protection*. This helps Kotlin Compiler to show an error at compile-time rather than runtime, for example In Java, java.util.Collections.unmodifiableList(java.util.List) the error would be only visible to the user when he tries to update the unmodifiable list at runtime.

read-only protections, are used to safeguard values in a collection from accidental 
updates

So how do we update Pair values?

It’s easy, you can directly use the copy constructor, for example :

pair copy constructor

The last thing in your mind would be, do we need to use ListOf<Pair<K,V>> or MutableListOf<Pair<K,V>> to create a mutable map?

To answer this, you need to know both List and MutableList both are of an iterable type so doesn’t matter, you can create a map using both.

Pairs to Map

Other part is you can’t directly convert a List or MutableList to MutableMap, there is no direct extension available :

map to mutable map no direct conversion

MutableMap is the base interface of AbstractMutableMap , HashMaps and LinkedHashMap.

mutableMapOf 👷‍♂️

Similar to Map signature, interface MutableMap<K, out V>, it’s an interface, i.e it needs to have an implementing class.

In Kotlin, we have two function implementation of these and both of them is resolved using LinkedHashMap

mutableMap stdlib functions
mutableMap resolved by linkedhashMap
mutableMap LinkedHashMap definition

TLDR ☕️

Mutable Maps :

  • Mutable Maps are modifiable key/value pairs of collection therefore contain functions such as put, remove, clear etc that can modify the map.
  • They use MutableEntry to represent the internal state of key/value
  • Pairs don’t have mutable counter-part, Pairs are used to create the map, then that map is transformed to MutableMap.
  • All of the function implementations is resolved by LinkedHashMap

HashMap 📝

In Kotlin JVM, HashMap is a type alias for Java’s HashMap

hashmap signature Kotlin | Java

HashMap in Java is a Hash table based implementation of the (Mutable) Map interface.

  • Insertion Order is not preserved, insertion is based on the hashcode of keys, not the values
  • Duplicate keys entry is not allowed
  • Heterogeneous key/value entry is allowed
  • Null keys are allowed but only once, you can store any null values

NOTE.

Even if Kotlin uses typealias and call Java Hashmap the interpolation with Kotlin maps its return types to the MutableMap interface of Kotlin, i.e when you call hashMap.entries you will get MutableSet<MutableEntry> not Java’s Set<Entry>.

Learn more about all the APIs of HashMap from:

hashMapOf 👷‍♂️

Kotlin provides two implementations to create HashMap

hashmap stdlib functions
hashmap from default constructor
Kotlin Hashmap of definition

Another way by which you can create a hashmap is by creating an object directly using any of the available java constructors.

directly create hashmap in kotlin

Convert Map to HashMap?

There is no direct extension to convert map to hashmap as it was available in mutable map, so you can :

map to hashmap in kotlin

TLDR ☕️

Hash Maps:

  • They are a direct port of java.util.HashMap, whose underlying implementation is based on HashTable.
  • Insertion Order is not preserved, because it’s sorted according to hashcode of the keys
  • No special Kotlin standard extension is available over them, you can directly create them using constructor or use standard static factory functions of Kotlin.
  • Mutable collection in nature.

LinkedHashMap ⛓📝

In Kotlin JVM, similar to HashMap, LinkedHashMap is a type alias for Java’s LinkedHashMap

LinkedHashMap signature

LinkedHashMap in Java is a Hash table and LinkedList based implementation of the (Mutable) Map interface.

  • Doubly LinkedList is used to preserve the order of insertion.
  • Features are similar to HashMap including methods and constructors.
  • Useful to create a Cache object that can expire data using some criteria that you define or LRUs ( least recently used ) by overriding the removeEldestEntry()

Check out my LRU implementation in Repository.

linkedMapOf ️️👷‍♂️

Kotlin provides two implementations to create LinkedHashMap

Linked hashmap stdlib function
linkedhashmap resolved in kotlin
linkedhashMap definition in kotlin

Other way by which you can create a Linkedhashmap is by creating an object directly using any of the available java constructors.

linkedhashmap created directly

Convert Map to LinkedHashMap?

There is no direct extension to convert map to hashmap as it was available in mutableMap, so you can :

map to linkedHashmap in kotlin

TLDR ☕️

LinkedHashMaps:

  • They are a direct port of java.util.LinkedHashMap<K,V>, whose underlying implementation is based on HashTable and LinkedList.
  • Doubly LinkedList is used to preserve the order of insertion
  • No special Kotlin standard extension are available over them, you can directly create them using constructors or use standard static factory functions of Kotlin.
  • Mutable collection in nature.

Bonus Points: 🤩

Since you made it this far in the post, here is your reward!

Some points that you need to know about maps :

HashMap/LinkedHashMap

  • They are not thread-safe, doesn’t have synchronized functions
  • The null key is allowed only once
  • Performs faster in the multithreaded environment due to lack of synchronization
  • They are not a legacy DS, HashMap introduced in 1.2, LinkedHashMap introduced in 1.4

HashTable

  • They are thread-safe
  • The null key isn’t allowed
  • Perform slow in the multithreaded environment due to synchronization
  • It is a legacy DS, introduced in 1.0

Conclusion 💆🏻‍♀️

Hopefully, you understand how Kotlin handles Collection over the JVM platform and some of the key points such as:

  • Entries that can’t be directly converted to Map,
  • Pair doesn’t have Mutable type,
  • It's not always true that your map is a linkedHashMap
  • Kotlin JVM resolves Hashmap and LinkedHashMap using Java APIs. etc

Hope you find the post informative, if like more such content you can gladly follow up on my personal blog at chetangupta.net , you can use the same link to contact me.

Until next time, Happy Hacking! 👨🏻‍💻.

Coding enthusiast! love Android #kotlinAlltheWay, want to explore all opportunity around it! CodingMantra: #cleanCoder #TDD #SOLID #designpatterns