Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: eliminate nulls from a List (or other functional transformation)

Problem

What is the idiomatic way of working around this limitation of the null-safety in the Kotlin type system?

val strs1:List<String?> = listOf("hello", null, "world")  // ERROR: Type Inference Failed: Expected Type Mismatch: // required: List<String> // round:    List<String?> val strs2:List<String> = strs1.filter { it != null } 

This question is not just about eliminating nulls, but also to make the type system recognize that the nulls are removed from the collection by the transformation.

I'd prefer not to loop, but I will if that's the best way to do it.

Work-Around

The following compiles, but I'm not sure it's the best way to do it:

fun <T> notNullList(list: List<T?>):List<T> {     val accumulator:MutableList<T> = mutableListOf()     for (element in list) {         if (element != null) {             accumulator.add(element)         }     }     return accumulator } val strs2:List<String> = notNullList(strs1) 
like image 360
GlenPeterson Avatar asked Jul 22 '16 21:07

GlenPeterson


People also ask

How do you clear Kotlin mutable list?

To remove all elements from a Mutable List in Kotlin, call clear() function on this list object.

What is mapNotNull?

mapNotNull( transform: (T) -> R? ): List<R> Returns a list containing only the non-null results of applying the given transform function to each element in the original array.

How do I add to Kotlin Mutablelist?

To add an element to a Mutable List in Kotlin, we can use add(element), or add(index, element) functions. add(element) adds element to the end of this Mutable List. add(index, element) adds element to this Mutable List at the given index.


1 Answers

You can use filterNotNull

Here is a simple example:

val a: List<Int?> = listOf(1, 2, 3, null) val b: List<Int> = a.filterNotNull() 

But under the hood, stdlib does the same as you wrote

/**  * Appends all elements that are not `null` to the given [destination].  */ public fun <C : MutableCollection<in T>, T : Any> Iterable<T?>.filterNotNullTo(destination: C): C {     for (element in this) if (element != null) destination.add(element)     return destination } 
like image 189
SerCe Avatar answered Sep 24 '22 04:09

SerCe