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 })