NPE при использовании map {} в ArrayList, содержащем NULL - PullRequest
3 голосов
/ 14 марта 2019

Я получаю

java.lang.NullPointerException: попытка вызвать виртуальный метод 'float java.lang.Number.floatValue ()' для ссылки на пустой объект

в следующем коде:

val localHistory: ArrayList<Float> = ArrayList<Float>()
...    
val strHistory = localHistory.map { value -> decoration.decoratedValue(ref.format, value) }

Я только что узнал, что ArrayList может содержать нули (окей).Это будет означать, что значение в замыкании преобразования карты может быть NULL, нет?

Но этого не может быть, поскольку значение не является необязательным типом, и компилятор говорит, что if (value! = Null) всегда будет истинным.

Итак, вопрос в том, как избежать NPE в этом случае?

Ответы [ 3 ]

6 голосов
/ 14 марта 2019

Я предлагаю пометить каждый параметр в Collection, который вы получаете от Java, как обнуляемые (если, конечно, вы не знаете, что это никогда не может быть null:

val floats: List<Float?> = someJavaClass.getFloats()

Тогда выможет отфильтровать null s и выполнить операцию на карте:

val newFloats: List<Float> = floats
    .filter { it != null }
    .map { it + 1 }

Имейте в виду, что каждая операция filter, map (и т. д.) будет выполнять итерацию всей коллекции и создавать новуюна каждый раз. Вам лучше использовать Sequence s, которые повторяются лениво.

Как уже упоминалось в комментариях, можно использовать filterNotNull для прямой фильтрации всех нулевых значений:

val newFloats: List<Float> = floats
    .filterNotNull()
    .map { it + 1 }

и mapNotNull для хранения только тех значений, которые map-функция не возвращает null, это также устраняет filterNotNull:

val newFloats: List<Float> = floats
    .mapNotNull { it?.plus(1) }

Другая конструкция, которую я могу придумать, работает с вашимпример, хотя он очень нечитабелен и просто сложен. Но вот он:

val strHistory = localHistory
    .mapNotNull { decoration.decoratedValue(ref.format, it ?: return@mapNotNull null) }
2 голосов
/ 14 марта 2019

Если вы просто хотите исключить нулевые значения в ArrayList, вызовите mapNotNull вместо map. Подробнее см. здесь .

Затем вам также необходимо обработать случай, когда value равен нулю внутри вашей лямбды, что вы можете сделать с ?.let, как показано ниже:

localHistory.mapNotNull { value -> value?.let { decoration.decoratedValue(ref.format, it) } }
0 голосов
/ 05 апреля 2019

Еще один с mapNotNull:

val strHistory = localHistory.mapNotNull { it ?: return@mapNotNull null
    decoration.decoratedValue(ref.format, it) }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...