Cpereira1
Cpereira1

Reputation: 37

Which one is more efficient using kotlin?

I have a collection with objects that contain a value field and I need reduce information objective which one is more efficent or better and why?.

 settings.filter {it.value != null }.forEach{
    doSomething ....
}

settings.forEach{
    if(it.value != null){
        doSomething ...
    }

Upvotes: 0

Views: 854

Answers (3)

gidds
gidds

Reputation: 18577

As other answers mention, the first example will create a temporary list in memory. In practice, this isn't usually worth worrying about — but as you say, if the list could be very big (say, tens of thousands of items or more) then it could become significant.

However, there's a ‘best of both worlds’ option, which is to use a sequence:

settings.asSequence()
        .filterNotNull()
        .forEach {
            // doSomething ....
        }

This looks like the first example (apart from the added asSequence() and line breaks), but performs about as well as the second. That's because sequences are evaluated lazily: in this case filterNotNull() doesn't create a new list, but adds an action that will be executed as part of the forEach. You can add futher processing steps in between, too, and nothing will actually get evaluated until it's needed.

There's a bit of overhead in setting it all up (which is why sequences aren't the default), but that overhead doesn't depend on the size of the list — so if you have big lists and/or lots of processing steps, it can save a lot of memory. (It can also save a lot of processing in cases where you're not using all the results, such as when the last operation is a find().)

Upvotes: 0

Tenfour04
Tenfour04

Reputation: 93609

filter allocates a list, so the second one will be faster. But if your list isn’t many hundreds of items long, the difference is negligible and you should choose what you think is more readable code. In this case I think the second one is easier to read anyway.

Upvotes: 4

Gowtham K K
Gowtham K K

Reputation: 3429

Here is the internal implementation of filter function used in Kotlin Collection.

public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
    return filterTo(ArrayList<T>(), predicate) // New Array List Object Creation
}

public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
    for (element in this) if (predicate(element)) destination.add(element)
    return destination
}

Here you can see, it creates new list. It creates an empty arraylist and add filtered elements to new list.

Adding to Tenfour04's answer, for small list you can use filter as its more idiomatic. If you need to go with optimal way, you can use non null check.

Also you do this more idiomatically like this,

settings.filterNotNull().forEach {} //It also create extra memory.

Or you can use create your own idiomatic foreach extension function filtering null values, without creating extra space

fun <T> Iterable<T?>.forEachNonNull(a: (T) -> Unit) {
    for (i in this) {
        if (i != null){
            a.invoke(i)
        }
    }
}

You can use like this.

settings.forEachNonNull {
}

Upvotes: 0

Related Questions