Kotlin - same condition: multiple if statements or one if statement

Viewed 6098

In Kotlin you can use if statements kind of like ternary operators.

We have the option to do something like this:

val x = if (isOdd) 1 else 2

but if we have multiple variables that need to be set based on some condition is it more correct to do it the old fashioned way like so:

val x: Int
val y: Int
val z: Int

if (isOdd) {
    x = 1
    y = 3
    z = 5
} else {
    x = 2
    y = 4
    z = 6
}

or like this :

val x = if (isOdd) 1 else 2
val y = if (isOdd) 3 else 4
val z = if (isOdd) 5 else 6

the second way looks much cleaner to me, but I'd like to know if the first method would be computed faster since it only needs to calculate the condition once whereas the second way needs to check the condition 3 times.

Is the second way actually slower or will it be optimized by the compiler?

3 Answers

I'd prefer something like this, looks way more Kotlinesque:

data class Point3D(val x: Int, val y: Int, val z: Int)

fun foo(isOdd: Boolean): Point3D = if (isOdd) Point3D(1, 3, 5) else Point3D(2, 4, 6)

//or using destructureing see https://kotlinlang.org/docs/reference/multi-declarations.html)
val (x,y,z) = if (isOdd) Triple(1, 3, 5) else Triple(2, 4, 6)

Also it combines the best of both, using if as expression and only one if is needed. (At the cost of an additional object allocation).

But to answer your question. Do what you like and think is most readable. Performance wise I doubt you will make a difference.

if is an expression in Kotlin, not a statement: it returns a value, whereas it doesn't in Java's case.

I don't think here is such an optimization issue you should ever think about, honestly. Premature optimization is a common source of problems. If this boolean variable is thread-confined, then I think the compiler will perform all the optimizations that are possible in this context, so it will be almost no overhead at all (if not completely).

Wise choice in OO languages is to prefer clearness and flexibility over low-level optimization issues (especially when compilers are able to resolve them).

Okay, so just saw this question again and got curious... So I did some tests.

Turns out there is actually a HUGE difference, heres the results:

Code

fun main() {
    for (i in 0 until 3) {
        val t1_s = System.currentTimeMillis()
        for (j in 0 until 100000) {
            when (i){
                0 -> a(j % 2 == 0)
                1 -> b(j % 2 == 0)
                2 -> c(j % 2 == 0)
            }
        }
        val t1_e = System.currentTimeMillis()
        println("Test $i - time ${t1_e - t1_s}")
    }
}

fun a(isOdd: Boolean): Int {
    val x: Int
    val y: Int
    val z: Int

    if (isOdd) {
        x = 1
        y = 3
        z = 5   
    } else {
        x = 2
        y = 4
        z = 6
    }
    
    return x + y + z
}

fun b(isOdd: Boolean): Int {
    val x = if (isOdd) 1 else 2
    val y = if (isOdd) 3 else 4
    val z = if (isOdd) 5 else 6
    
    return x + y + z
}

fun c(isOdd: Boolean): Int {
    val (x,y,z) = if (isOdd) Triple(1, 3, 5) else Triple(2, 4, 6)
    
    return x + y + z
} 

Output

Test 0 - time 3
Test 1 - time 1
Test 2 - time 8

It seems my second solution is the fastest, my first suggestion next, and the top answer as MUCH slower.

Does any one know why this might be? Obviously these are milliseconds so it almost always wouldn't matter, but it is neat to think that one method is 5-10 times faster

EDIT:

So tried bumptin the iterations up to 100000000 and the results were:

Test 0 - time 6
Test 1 - time 41
Test 2 - time 941

I Guess the first 2 options are getting optimized out but the third option is always creating a new object making it much slow

Try it online!

Related