Reputation: 910
I am trying to find better way to chain the filter
and map
operators in Kotlin. What I want to do is to filter the null items before going to the map
operator.
I was able to chain them, but the compiler complained about the nullability of my list items.
class Person(val age : String?)
fun foo(age :String){
// require non-null age
}
The sample usage was:
val list = mutableListOf(Person("3"), Person("2"))
list.filter{ it.age != null }.map{ foo(it.age) }
// The IDE wants me to add !!
So why can't Kotlin infer the nullability? The filtered (all non-null) items passed down to map should had been filtered to ensure that they are non-null.
Upvotes: 1
Views: 1292
Reputation: 28322
This case may seem easy for a human, but technically speaking it would be really hard for the compiler to understand that after filtering it is a list of people
objects, but with different type of the age
property than original.
If you don't use a whole people
instance at map()
stage then I think the easiest would be to do:
list
.mapNotNull { it.age }
.map(::foo)
Or, if your foo()
can't return nulls:
list.mapNotNull { it.age?.let(::foo) }
But I think this is less readable. Or you can just use !!
- it's not that bad if we know what we're doing.
Upvotes: 1
Reputation: 5853
You can replace filter
and map
with one method mapNotNull:
val list2 = list.mapNotNull { it.age }
Upvotes: 4
Reputation: 5980
You can use the Iterable<T>.filterNotNull()
extension function here which will return a list of the non-nullable type.
In your case, the compiler just isn't advanced enough to smart-cast the filtered list, it would be quite a lot to ask. So if you need to use filter
specifically you would have to add an assertion.
Upvotes: 0