在包含 NULL 的 ArrayList 上使用 map 时的 NPE
Posted
技术标签:
【中文标题】在包含 NULL 的 ArrayList 上使用 map 时的 NPE【英文标题】:NPE when using map on ArrayList containing NULLs在包含 NULL 的 ArrayList 上使用 map 时的 NPE 【发布时间】:2019-08-05 02:06:24 【问题描述】:我明白了
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 可能包含空值 (oookay)。这意味着地图转换闭包中的 value 可能为 NULL,不是吗?
但这不可能,因为 value 不是可选类型,并且编译器说 if (value != null) 将始终为真。
那么问题是在这种情况下如何避免 NPE?
【问题讨论】:
您是如何填写ArrayList
的?你是用 kotlin 还是 java 做的?
好问题。它实际上是由 GSON 反序列化的,所以它应该是 Java
当然,列表可以包含null
。在这种情况下,自动拆箱将失败(从Float
转换为float
),这显然是在这里完成的。一旦这个自动拆箱成功,变量value
(这显然是一个原始的float
)就不能再是null
了。
Json 可以包含任何null
值吗?如果是,请将您从 java 获得的集合标记为 ArrayList<Float?>
,然后过滤掉可能的 null
值
那么我有什么选择可以防止这种情况失败?
【参考方案1】:
我建议将您从 Java 收到的 Collection
中的每个参数都标记为可为空(当然,除非您知道它永远不可能是 null
:
val floats: List<Float?> = someJavaClass.getFloats()
然后您可以过滤掉null
s 并进行地图操作:
val newFloats: List<Float> = floats
.filter it != null
.map it + 1
请记住,每个filter
、map
(等等)操作都会迭代整个集合并每次都创建一个新集合。你最好使用Sequence
s,它是惰性迭代的。
正如 cmets 中提到的,可以使用filterNotNull
直接过滤掉所有空值:
val newFloats: List<Float> = floats
.filterNotNull()
.map it + 1
而mapNotNull
只保留映射函数不返回null
的值,这也消除了filterNotNull
:
val newFloats: List<Float> = floats
.mapNotNull it?.plus(1)
我能想到的另一个结构适用于您的示例,尽管它非常不可读且很复杂。但这里是:
val strHistory = localHistory
.mapNotNull decoration.decoratedValue(ref.format, it ?: return@mapNotNull null)
【讨论】:
另请注意,您可以使用filterNotNull()
而不是filter it != null
。【参考方案2】:
如果您只想排除ArrayList
中的空值,请调用mapNotNull
而不是map
。详情请见here。
您还需要处理 value
在您的 lambda 中为 null 的情况,您可以使用 ?.let
进行处理,如下所示:
localHistory.mapNotNull value -> value?.let decoration.decoratedValue(ref.format, it)
【讨论】:
我得到编译器建议,当我尝试使用 mapNotNull 时没有必要 将声明更改为ArrayList<Float?>
以告诉编译器该列表可能包含空条目。【参考方案3】:
还有一个 mapNotNull:
val strHistory = localHistory.mapNotNull it ?: return@mapNotNull null
decoration.decoratedValue(ref.format, it)
【讨论】:
以上是关于在包含 NULL 的 ArrayList 上使用 map 时的 NPE的主要内容,如果未能解决你的问题,请参考以下文章
在带有整数数组的 ArrayList 上使用 contains
在 Java 中序列化和保存 double [] 的 ArrayList
使用 volley 将 ArrayList 发送到服务器时在响应中收到 null