Reputation: 5858
I am kinda new using kotlin and I was wondering if I can do something like this.
I have a list with objects of type Person
,
Person
has properties like name, id
but can be null.
So I made something like this:
return persons.filter {
it.name != null && it.id != null
}.map {
it.id to it.name
}.toMap()
I personally dont see the error but the compiler keeps telling me I should return a map of not nulls.
Is there any way I can do it using filter and map using lambdas functions?
Upvotes: 1
Views: 441
Reputation: 1906
May be you can simply change
.map {
it.id to it.name
}
into
.map {
it.id!! to it.name!!
}
The suffix !!
operator converts String?
into String
, throwing exception if the value with type String?
is null
, which in our case can't be true, due to the previously applied filter.
Use of !!
should be limited to cases where you take responsibility of explicitly asserting that value can't be null: you're saying to the compiler that values are String
even if the type is String?
- and should be imho used with caution.
Compiler can't infer the type domain restriction from String?
to String
from the predicate passed to filter
, but you can, so I think !!
usage can be a valuable approach...
Upvotes: 2
Reputation: 8422
btw, you can even get rid of if
in mapNotNull
:
persons.mapNotNull {
val id = it.id ?: return@mapNotNull null
val name = it.name ?: return@mapNotNull null
id to name
}.toMap()
Upvotes: 3
Reputation: 170713
Use mapNotNull
to combine filter
and map
:
persons.mapNotNull {
val id = it.id
val name = it.name
if (id != null && name != null) Pair(id, name) else null
}.toMap()
Pulling id
and name
into local variables should make sure they'll get inferred as not-null in Pair(id, name)
but may not be necessary.
The reason your approach doesn't work is that persons.filter { ... }
just returns List<Person>
, there's no way to say "list of Person
s with non-null name
and id
" or to represent it internally in the compiler.
Upvotes: 3