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

Arn*_*gel 3 java null dictionary nullpointerexception kotlin

我越来越

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法'float java.lang.Number.floatValue()'

在以下代码上:

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

我刚刚了解到ArrayList可能包含空值(oookay)。那将意味着映射转换闭包中的可能为NULL,不是吗?

但这不能是因为不是可选类型,并且编译器说if(value!= null)将始终为true。

那么问题是在这种情况下如何避免NPE?

Lin*_*ica 6

我建议将Collection您从Java接收到的参数中的每个参数都标记为可为空(除非您知道它永远不会null

val floats: List<Float?> = someJavaClass.getFloats()
Run Code Online (Sandbox Code Playgroud)

然后,您可以过滤出nulls并执行地图操作:

val newFloats: List<Float> = floats
    .filter { it != null }
    .map { it + 1 }
Run Code Online (Sandbox Code Playgroud)

请记住,每一个filtermap(等)操作将遍历整个集合,并在每次创建一个新的。最好使用Sequences,它们是延迟进行迭代的。

如评论中所述,可以filterNotNull用来直接过滤掉所有空值:

val newFloats: List<Float> = floats
    .filterNotNull()
    .map { it + 1 }
Run Code Online (Sandbox Code Playgroud)

mapNotNull只保留哪些地图功能不返回值null,这也消除了filterNotNull

val newFloats: List<Float> = floats
    .mapNotNull { it?.plus(1) }
Run Code Online (Sandbox Code Playgroud)

我可以想到的另一种构造虽然很不易理解,却很复杂,但可以与您的示例一起使用。但是这里是:

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