Kotlin program to find one element in a list of objects

Introduction :

In this Kotlin programming tutorial, we will learn how to find one element in a list of objects. Kotlin provides different ways to find values in a list. We will explore these with examples.

using find() :

find() takes one predicate that returns one boolean. Based on this predicate, it will return the first element found or null if no element is found.

As we have a list of objects, we will compare the object properties in the predicate.

Example program :

The below example program explains how to use find :

data class Month(val name: String, val days: Int, val index: Int)

fun main() {
    val monthList =
        listOf(
            Month("January", 31, 0),
            Month("April", 30, 1),
            Month("May", 31, 2),
            Month("January", 31, 3),
            Month("July", 31, 4)
        )

    val april = monthList.find { it.name == "April" && it.days == 30 }
    val feb = monthList.find { it.name == "February" && it.days == 28 }
    val january = monthList.find { it.name == "January" && it.days == 31 }

    println(april)
    println(feb)
    println(january)
}

Explanation :

  • Month is a data class with three properties : String name, Integer days and Integer index.

  • monthList is a list of Month objects with five different objects.

  • We are finding three different months in this list. Each find compares the name and days of the finding object in the predicate.

  • Finally, we are printing the objects that we got from find.

  • april is the Month object with name April and days 30. We have only one April Month object in the list. feb is not in the list, so it will return null and january is the first Month object with name January and days 31.

Note that we have two January objects available but the first object i.e. index 0 is returned.

Output :

This program will print the below output :

Month(name=April, days=30, index=1)
null
Month(name=January, days=31, index=0)

findLast :

findLast is similar to find. The only difference is that it returns the last element that matches a given predicate. If no element is found, it returns null. Let’s try the above example list with findLast :

val april = monthList.findLast { it.name == "April" && it.days == 30 }
val feb = monthList.findLast { it.name == "February" && it.days == 28 }
val january = monthList.findLast { it.name == "January" && it.days == 31 }

It will print :

Month(name=April, days=30, index=1)
null
Month(name=January, days=31, index=3)

The first and the second objects are the same because we have only one April Month object and no February Month objects.

But we have two Month objects with name January and days 31. findLast will return the last element i.e. the object with index = 3.

Get the index - indexOfFirst or indexOfLast :

indexOfFirst or indexOfLast returns the first or the last element matches with a given predicate. If the list doesn’t contain any element defined by the predicate, it will return -1.

It requires one more step, list[index], to get the element from the list. Also, we need to make sure that we do one check before passing the index because for index = -1, it will throw ArrayIndexOutOfBoundsException.

To get similar output as the above examples, we can do something like below :

data class Month(val name: String, val days: Int, val index: Int)
fun getElement(list : List<month>,index: Int) : Month?{
    if(index == -1) return null
    return list[index]
}
fun main() {
    val monthList =
        listOf(
            Month("January", 31, 0),
            Month("April", 30, 1),
            Month("May", 31, 2),
            Month("January", 31, 3),
            Month("July", 31, 4)
        )
    val aprilIndex = monthList.indexOfFirst { it.name == "April" && it.days == 30 }
    val febIndex = monthList.indexOfFirst { it.name == "February" && it.days == 28 }
    val januaryIndex = monthList.indexOfFirst { it.name == "January" && it.days == 31 }
    println(getElement(monthList,aprilIndex))
    println(getElement(monthList,febIndex))
    println(getElement(monthList,januaryIndex))
}

We have created one function getElement, that takes one list of Month and one index and returns the Month object for that index. If index is -1, it returns null.

It will print :

Month(name=April, days=30, index=1)
null
Month(name=January, days=31, index=0)

first, firstOrNull, last, lastOrNull :

first method returns the first element found using the provided predicate. If it doesn’t find any element, it throws NoSuchElementException.

Similarly, firstOrNull and lastOrNull returns the first or the last element if found using the predicate. Else, it returns null.

For the above example, if we use the below statements :

val april = monthList.firstOrNull { it.name == "April" && it.days == 30 }
val feb = monthList.firstOrNull { it.name == "February" && it.days == 28 }
val january = monthList.firstOrNull { it.name == "January" && it.days == 31 }

It will print the below output :

Month(name=April, days=30, index=1)
null
Month(name=January, days=31, index=0)

single, singleOrNull :

single returns the single element that matches a predicate. If there is no element or more than one element, it will throw one exception.

singleOrNull returns the element that matches the predicate. If the collection is empty or it has more than one element, it will return null.

singleOrNull is safer than single and both are useful only if we have unique elements. For example :

val april = monthList.singleOrNull { it.name == "April" && it.days == 30 }
val feb = monthList.singleOrNull { it.name == "February" && it.days == 28 }
val january = monthList.singleOrNull { it.name == "January" && it.days == 31 }

This will print :

Month(name=April, days=30, index=1)
null
null

Similar tutorials :