1. Introduction

Lists and Maps are core data structures in Kotlin and are commonly used to accomplish a myriad of programming tasks. Frequently, lists of key-value pairs are transformed into maps to enhance the organization of our data. However, there may be instances where the key-value pairs contain null values that are not required in the final map.

In this tutorial, we’ll explore various ways to skip null values when converting a list of pairs to a map in Kotlin.

2. Using a for() Loop

A simple approach to skipping null values when converting a list of pairs to a map is to use the classic for() loop. We iterate through each element of the list and check if the value is null. If the value is not null, we add the pair to the map:

@Test
fun `Skips null values using for loop`() {
    val pairs = listOf<Pair<String, Int?>>(Pair("a", 1), Pair("b", null), Pair("c", 3))
    val expected = mapOf("a" to 1, "c" to 3)
    val map = mutableMapOf<String, Int>()
    for (pair in pairs) {
        if (pair.second != null) {
            map[pair.first] = pair.second!!
        }
    }

    assertEquals(expected, map)
}

In the above code, we construct a list of pairs that contain a null value. Next, we create an empty MutableMap and then iterate through each element of the list. If the value of the pair is not null, we add the pair to the map. Otherwise, we skip that pair. Finally, we assert that the map we end up with contains the correct entries.

3. Using the filter() Method

Another approach is to use the filter() method. This method accepts a predicate lambda function and filters the list, retaining elements that match the predicate:

@Test
fun `Skips null values using the filter method`() {
    val list = listOf<Pair<String, Int?>>(Pair("a", 1), Pair("b", null), Pair("c", 3))
    val filteredList = list.filter { it.second != null }
    val map = filteredList.toMap()
        
    val expected = mapOf("a" to 1, "c" to 3)
    
    assertEquals(expected, map)
}

Similarly, we create a list of pairs that contain a null value. Subsequently, we supply the filter() method with a predicate function that removes any pair with a null value. Finally, we convert the list to a map after filtering using the toMap() method.

4. Using the mapNotNull() Method

We can also leverage the mapNotNull() method to skip null values when converting a list of pairs to a map. This method applies a transformation on each element of the list and returns a new list containing only non-null values:

@Test
fun `Skips null values using the mapNotNull method`() {
    val pairs = listOf<Pair<String, Int?>>(Pair("a", 1), Pair("b", null), Pair("c", 3))
    val expected = mapOf("a" to 1, "c" to 3)
    val result = pairs.mapNotNull { it.second?.let { value -> it.first to value } }.toMap()
        
    assertEquals(expected, result)
}

In the code snippet above, we call the mapNotNull() method on a list of pairs to transform the list into a new list containing only non-null values.

The transformation applies to each element of the list and either returns a new pair with the first element of the original pair and the non-null value of the second element, or null if the second element is null.

The mapNotNull() method skips any null elements and does not include them in the resulting list. This results in a final map from toMap() without the null elements.

5. Using the fold() Method

We can also use the fold() method to skip null values while converting a list of pairs to a map. This method combines the elements of a collection into a single value using a specified operation.

This method runs an accumulation lambda on each element of the list to accumulate the result. In this case, we’ll accumulate the results in a map while skipping null values:

@Test
fun `Skips null values using the fold method`() {
    val pairs = listOf<Pair<String, Int?>>(Pair("a", 1), Pair("b", null), Pair("c", 3))
    val expected = mapOf("a" to 1, "c" to 3)
    val map = pairs.fold(mutableMapOf<String, Int>()) { acc, pair ->
        acc.apply {
            if (pair.second != null){
                put(pair.first, pair.second!!)
            }
        }
    }

    assertEquals(expected, map)
}

In this test, we use the fold() method on a list of pairs to iterate over each element in the list and skip null values. The lambda function we pass to the fold() method checks if the second value of the pair is not null. If that’s the case, we add the pair to a mutable map. Finally, we always return the accumulator map as the result of the intermediary accumulation lambda.

6. Conclusion

In this article, we’ve explored various ways to skip null values when converting a list of pairs to a map in Kotlin. The filterNotNull() method filters out null values from the list, while the mapNotNull() method applies a transformation on each element of the list and returns a new list containing only non-null transformed values.

Additionally, the for() loop approach iterates a list of pairs and checks if the value is null. Finally, The fold() method applies an operation on each element of the list and accumulates the results.