NPE when using map {} on ArrayList containing NULLs

Arnie Schwarzvogel :

I'm getting

java.lang.NullPointerException: Attempt to invoke virtual method 'float java.lang.Number.floatValue()' on a null object reference

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). That would mean that the value in the map transforming closure may be NULL, no?

But this cannot be since the value is not an optional type and the compiler says that if (value != null) will be always true.

So the question is how to avoid NPE in this case?

Lino :

I suggest marking every parameter in a Collection you receive from Java as nullable (unless of course you know it can never be null:

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

Then you can filter out the nulls and do your map operation:

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. You're better of using Sequences, which are iterated lazily.

As mentioned in the comments one may use filterNotNull to directly filter out all null values:

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:

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) }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=86384&siteId=1