简体   繁体   English

在包含NULL的ArrayList上使用map {}时的NPE

[英]NPE when using map {} on ArrayList containing NULLs

I'm getting 我越来越

java.lang.NullPointerException: Attempt to invoke virtual method 'float java.lang.Number.floatValue()' on a null object reference java.lang.NullPointerException:尝试在空对象引用上调用虚方法'float java.lang.Number.floatValue()'

on following code: 在以下代码:

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

I've just learned that ArrayList may contain nulls (oookay). 我刚刚了解到ArrayList可能包含空值(oookay)。 That would mean that the value in the map transforming closure may be NULL, no? 这意味着map转换闭包中的可能为NULL,不是吗?

But this cannot be since the value is not an optional type and the compiler says that if (value != null) will be always true. 但这不可能是因为该不是可选类型,并且编译器说if(value!= null)将始终为true。

So the question is how to avoid NPE in this case? 所以问题是在这种情况下如何避免NPE?

I suggest marking every parameter in a Collection you receive from Java as nullable (unless of course you know it can never be null : 我建议将从Java接收的Collection每个参数标记为可为空(除非你知道它永远不会null

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

Then you can filter out the null s and do your map operation: 然后你可以过滤掉null并执行你的map操作:

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

Keep in mind that every filter , map (and so on) operation will iterate the whole collection and create a new on everytime. 请记住,每个filtermap (等等)操作都将迭代整个集合并在每次创建新的集合。 You're better of using Sequence s, which are iterated lazily. 你最好使用Sequence ,它是懒惰的迭代。

As mentioned in the comments one may use filterNotNull to directly filter out all null values: 如评论中所述,可以使用filterNotNull直接过滤掉所有空值:

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

And mapNotNull to only keep values which map-function doesn't return null , this also eliminates the filterNotNull : 并且mapNotNull只保留map-function不返回null ,这也消除了filterNotNull

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

Another construct I can think of which works with your example though it is highly unreadable and just complex. 我能想到的另一个构造与你的例子有关,虽然它非常难以理解且复杂。 But here it is: 但这里是:

val strHistory = localHistory
    .mapNotNull { decoration.decoratedValue(ref.format, it ?: return@mapNotNull null) }

If you just want to exclude the null values in the ArrayList , call mapNotNull instead of map . 如果您只想排除ArrayList的空值,请调用mapNotNull而不是map See here for details. 详情请见此处

You then also need to handle the case where the value is null inside your lambda, which you can do with the ?.let as shown below: 然后,您还需要处理lambda中value null的情况,您可以使用?.let ,如下所示:

localHistory.mapNotNull { value -> value?.let { decoration.decoratedValue(ref.format, it) } }

One more with mapNotNull: 还有一个mapNotNull:

val strHistory = localHistory.mapNotNull { it ?: return@mapNotNull null
    decoration.decoratedValue(ref.format, it) }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM