Search code examples
kotlinarraylistcollectionskotlin-extensionkotlin-null-safety

Kotlin. How to map only non null values of list?


I need to make some operations with my list.

For example I have list of TestData:

data class TestData (
    val value: Int?,
    val name: String
)

I need to map list of TestData to list of String. Here is my code:

 val names = listOfTestData
              .map { data -> getName(data.value) } <- Type mismatch. Required: Int, found Int?
              .distinct()

The problem is that the function getName(value: Int) accepts only a non nullable type. Can I somehow skip elements from listOfTestData whose value is null ?

I could filter the values before making a map, but I'll have to use inside the map !!, I'd like a more elegant solution.

 val names = listOfTestData
                  .filter { it.value != null }
                  .map { data -> getName(data.value!!) } 
                  .distinct()

Please tell me how can this be done without using !!


Solution

  • Instead of filter, you can mapNotNull to the values. This is basically a map, but if the mapping function you provide returns null, the element is filtered out.

    listOfTestData.mapNotNull { it.value }
        .map { getName(it) }
        .distinct()
    

    This will go over the list 3 times. You can combine the mapNotNull and map by using a ?.let on the value:

    listOfTestData.mapNotNull { data -> data.value?.let { getName(it) } }.distinct()
    

    Alternatively, use a sequence:

    listOfTestData.asSequence()
        .mapNotNull { it.value }
        .map { getName(it) }
        .distinct()
        .toList()