Почему фильтрация пустых ключей карты не меняет тип на nullable в kotlin? - PullRequest
0 голосов
/ 27 марта 2020

У меня есть список объектов с необязательным идентификатором String, и я хочу сделать из него карту. Я хочу, чтобы ключи моей карты были не обнуляемыми: что-то вроде этого:

data class Foo(
  val id: String? = null
  val someStuff: String? = null,
)

val foo = listOf(Foo("id1"), Foo())
val bar = foo.filterNot { it.id == null }.associateBy { it.id }

Здесь bar тип Map<String?, Foo>, но не Map<String, Foo>

Мой обходной путь чтобы добавить ненулевой заявленный вызов: !!, но он не кажется чистым.

Есть ли простой и безопасный способ сделать это?

Ответы [ 2 ]

1 голос
/ 27 марта 2020

Существует запрос шестилетней давности на открытую функцию для Map.filterNotNullKeys() и запрос четырехлетней давности на открытую функцию для Map.associateByNotNull().

На мой взгляд, associateBy { it.id!! } будет наиболее чистым для удобства чтения. Но вы можете сделать это следующим образом:

val bar = foo.mapNotNull { it.id?.run { it.id to it } }.toMap()

Что касается вашего реального вопроса, то logi c - слишком много шагов для компилятора. Ваш последний вызов функции associateBy видит обнуляемое значение, поэтому оно выдает обнуляемое значение. Чтобы компилятор понял это, ему нужно было бы отступить назад и увидеть, что список, который вы вызываете associateBy, случайно отфильтровал определенные объекты таким образом, чтобы гарантировать, что определенное свойство, допускающее значение NULL, не будет нулевым. в этом списке c, и это то же свойство, с которым вы связываетесь. Теперь представьте, что это нужно делать для каждого вызова любой обобщенной функции c, и различные задействованные лямбды могут иметь несколько строк кода. Время компиляции взлетело бы до небес.

1 голос
/ 27 марта 2020

Это похоже на то, с чем contracts может помочь, но в настоящее время выражение contract не может получить доступ к свойствам используемого класса.

В качестве обходного пути вы можете определить второй класс, который имеет ненулевое значение id, например

data class Foo(
    val id: String? = null,
    val someStuff: String? = null
)

data class Foo2(
    val id: String,
    val someStuff: String? = null
)

val foo = listOf(Foo("id1"), Foo())
val bar = foo
    .mapNotNull { if (it.id != null) Foo2(it.id, it.someStuff) else null }
    .associateBy { it.id }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...