Blog / April 23, 2022 / 5 mins read / By Suneet Agrawal

Map Operator : Kotlin

The collection is something which is used by almost everyone. It makes our life easy. List, Set and Map are the best examples of them.

To iterate, filter or modify the existing collection object, Kotlin provides us with a few in builds transform operators. Map operator is one of them.

Lets try to understand the map operator in detail.

What is map operator?

Map operator is used to create a new collection object by iterating over the existing collection object and applying some transformation to it. The transformation that needs to be applied is passed as lambda to the function.

Since the map operator is an extension of the Iterable Interface, it can be used with all three collections ie List, Set and Map.

/**
 * Returns a list containing the results of applying the given [transform] function
 * to each element in the original collection.
 * 
 * @sample samples.collections.Collections.Transformations.map
 */
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
    return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

Map also has other few functions as below,

  • mapNotNull used for iteration and apply a transform to it but only to the non-null values. This will skip all null values in the list.

  • mapIndexed used for indexed iteration and apply a transform to it.

  • mapIndexedNotNull used for indexed iteration and apply a transform to it but only to the non-null values. This will skip all null values in the list.

/**
 * Returns a list containing only the non-null results of applying the given [transform] function
 * to each element in the original collection.
 * 
 * @sample samples.collections.Collections.Transformations.mapNotNull
 */
public inline fun <T, R : Any> Iterable<T>.mapNotNull(transform: (T) -> R?): List<R> {
    return mapNotNullTo(ArrayList<R>(), transform)
}

/**
 * Returns a list containing the results of applying the given [transform] function
 * to each element and its index in the original collection.
 * @param [transform] function that takes the index of an element and the element itself
 * and returns the result of the transform applied to the element.
 */
public inline fun <T, R> Iterable<T>.mapIndexed(transform: (index: Int, T) -> R): List<R> {
    return mapIndexedTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

/**
 * Returns a list containing only the non-null results of applying the given [transform] function
 * to each element and its index in the original collection.
 * @param [transform] function that takes the index of an element and the element itself
 * and returns the result of the transform applied to the element.
 */
public inline fun <T, R : Any> Iterable<T>.mapIndexedNotNull(transform: (index: Int, T) -> R?): List<R> {
    return mapIndexedNotNullTo(ArrayList<R>(), transform)
}

Map with List

map operator can be used over a list to transform its elements and return the resultant list. It can be used with a named parameter or using it.

val list = listOf(1, 2, 3, 4, 5)
    
val mapList = list.map{item -> item * 10}
println(mapList)

val mapList2 = list.map{ it * 10 }
println(mapList2)

val mapNotNullList = list.mapNotNull{ if (it % 2 == 0) null else it }
println(mapNotNullList)

map can also be used to transform a list of one data type to a list of another data type. In the below example, List of Int is converted to List of String.

val list = listOf(1 , 2, 3, 4, 5)

val stringList = list.map{ it.toString()}
    
println(stringList::class.simpleName) 
//this will print: ArrayList

println(stringList[0]::class.simpleName)
//this will print: String

In the case of mapIndexed and mapIndexedNotNull, since we have two variables passed in the lambda function, we can not skip the named parameters.

val list = listOf(1, 2, 3, 4, 5)
    
val mapIndexedList = list.mapIndexed{index, item -> index * item }
println(mapIndexedList)

val mapIndexedNotNullList = list.mapIndexedNotNull{
        index, item -> if (it % 2 == 0) null 
                        else (item * index) 
}
println(mapIndexedNotNullList)

Map with Set

Similar to List, map operator can be used over a set to transform its elements and return the resultant set. It can be used with a named parameter or using it.

val set = setOf(1, 2, 3, 4, 5)

val mapSet = set.map{item -> item * 10}
println(mapSet)

val mapSet2 = set.map{ it * 10 }
println(mapSet2)

val mapSetNotNull = list.mapNotNull{ if (it % 2 == 0) null else it }
println(mapSetNotNull)

map can also be used to transform a set of one data type to a list of another data type. In the below example, Set of Int is converted to Set of String.

val set = setOf(1, 2, 3, 4, 5)
    
val stringSet = set.map{ it.toString()}
    
println(stringSet::class.simpleName)
//this will print: ArrayList

println(stringSet[0]::class.simpleName)
//this will print: String

In the case of mapIndexed and mapIndexedNotNull, since we have two variables passed in the lambda function, we can not skip the named parameters.

val set = setOf(1, 2, 3, 4, 5)
    
val mapIndexedSet = set.mapIndexed{index, item -> index * item }
println(mapIndexedSet)

val mapIndexedNotNullSet = set.mapIndexedNotNull{
        index, item -> if (it % 2 == 0) null 
                        else (item * index) 
}
println(mapIndexedNotNullSet)

Map with Map

map operator can be used with map collection similar to the list and set using below functions and named parameters. There are no mapIndexed and mapIndexedNotNull functions in case of map collection.

val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3)

println(numbersMap.map { entry -> 
        entry.key to (entry.value * 10) 
})

println(numbersMap.mapNotNull { it })

In the case of using a map operator with a map collection, we can also iterate over all keys or values of the map collection and apply the transformation to it.

val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3)
    
println(numbersMap.mapKeys { it.key.uppercase() })

println(numbersMap.mapValues { it.value + it.key.length })
Comments