Is there any more Kotlin-esque way to achieve the ...
# getting-started
g
Is there any more Kotlin-esque way to achieve the effect outlined here?
Background: The class JavaObject has two properties Foo and Bar, which may be null. I want to map them to instances of a Kotlin class, but only for those instances where both fields are not null.
Migrating the
JavaObject
class in the first place is not an option.
w
Maybe like this?
Copy code
javaObjects
                .mapNotNull {
                    val foo = it.fooProperty ?: return@mapNotNull null
                    val bar = it.barProperty ?: return@mapNotNull null
                    KotlinDataClass(foo, bar)
                }
At least is more readable, I guess.
g
Thanks for the suggestion! I for one would argue that the long
return@mapNotNull null
kills readability even more, but I guess that's just personal taste
w
I agree, I don't like even the early
return
in the code, but I remember having this case before, and the team agreed was more readable those
return@
than the enclosed `let`s.
🤔 Can create an extension too:
Copy code
fun <T, Z> Pair<T?, Z?>.pairOrNull(): Pair<T, Z>? {
            val first = first ?: return null
            val second = second ?: return null
            return Pair(first, second)
        }
        
        fun doSomething(javaObjects: List<JavaObject>): List<KotlinDataClass> =
                javaObjects
                        .mapNotNull {
                            Pair(it.fooProperty, it.barProperty)
                                    .pairOrNull()
                                    ?.let { (foo, bar) -> KotlinDataClass(foo, bar) }
                        }
r
Honestly, I'd avoid the functional approach in this case:
Copy code
fun doSomething(javaObjects: List<JavaObject>): List<KotlinDataClass> {
    val data = mutableListOf<KotlinDataClass>()
    for (j in javaObjects) data += KotlinDataClass(
        j.fooProperty ?: continue,
        j.barProperty ?: continue
    )
    return data
}
a
Or make a
NullableKotlinDataClass
"factory" method?
Copy code
fun NullableKotlinDataClass(foo: Any?, bar: Any?): KotlinDataClass? {
    return KotlinDataClass(foo ?: return null, bar ?: return null)
}
fun doSomething(javaObjects: List<JavaObject>): List<KotlinDataClass> {
    return javaObjects.mapNotNull {
        NullableKotlinDataClass(it.fooProperty, it.barProperty)
    }
}
Perhaps as an extension function on
JavaObject
so you can do:
Copy code
fun JavaObject.toKotlinDataClassOrNull(): KotlinDataClass? {
    return KotlinDataClass(fooProperty ?: return null, barProperty ?: return null)
}
fun doSomething(javaObjects: List<JavaObject>): List<KotlinDataClass> {
    return javaObjects.mapNotNull(JavaObject::toKotlinDataClassOrNull)
}
u
For completeness' sake, you can also just use an
if
instead of the
let
nesting:
Copy code
class Foo(val a: String?, val b: String?)
    class Bar(val a: String, val b: String)

    fun foo(foos: List<Foo>): List<Bar> =
        foos.mapNotNull {
                if (it.a != null && it.b != null)
                    Bar(it.a, it.b)
                else null
            }
        }