jpganz18
jpganz18

Reputation: 5858

how can I clean my map to return Map<String, String> Instead Map<String? , String?> In kotlin?

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

Answers (3)

Pietro Martinelli
Pietro Martinelli

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

Andrei Tanana
Andrei Tanana

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

Alexey Romanov
Alexey Romanov

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 Persons with non-null name and id" or to represent it internally in the compiler.

Upvotes: 3

Related Questions