Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between find and firstOrNull?

Given the following code extracted from Kotlin Koans:

fun Shop.findAnyCustomerFrom(city: City): Customer? {     // Return a customer who lives in the given city, or null if there is none     return customers.firstOrNull { it.isFrom(city) } } 

My own solution used customers.find. Both work in the koan scenario.

The documentation for firstOrNull and find seem to be very similar.

What is the difference between these two functions?

like image 764
Kyll Avatar asked Aug 05 '17 09:08

Kyll


People also ask

What is firstOrNull?

firstOrNull( predicate: (UShort) -> Boolean. ): UShort? Returns the first element matching the given predicate, or null if element was not found.

What is predicate in Kotlin?

In Kotlin, filtering conditions are defined by predicates – lambda functions that take a collection element and return a boolean value: true means that the given element matches the predicate, false means the opposite.


1 Answers

In this thread from 2014, Kotlin community members and JetBrains staff discuss the merits of the different methods find and firstOrNull:

https://youtrack.jetbrains.com/issue/KT-5185

While not an official statement, JetBrains' employee Ilya Ryzhenkov describes it as:

I think we can undeprecate find and make it an alias to firstOrNull. Much like indexOf has well-known semantics, find is also widely recognised as "find first item matching predicate or return null if nothing is found". People who like precise meaning can use firstOrNull, singleOrNull to express the intent.

In other words:

  • find(predicate) and firstOrNull(predicate) are identical in behaviour and find can be considered alias of firstOrNull
  • find is kept around as an alias because it's more intuitive and discoverable for programmers not already familiar with these Linq-style - or functional - methods.

In actuality the definition of Array<out T>.find is not defined as an alias, but as a wrapper (though the optimizing compiler will inline it, effectively making it an alias):
https://github.com/JetBrains/kotlin/blob/1.1.3/libraries/stdlib/src/generated/_Arrays.kt#L657

@kotlin.internal.InlineOnly public inline fun <T> Array<out T>.find(predicate: (T) -> Boolean): T? {     return firstOrNull(predicate) } 

Ditto for Sequence<T>.find:
https://github.com/JetBrains/kotlin/blob/1.1.3/libraries/stdlib/src/generated/_Sequences.kt#L74

@kotlin.internal.InlineOnly public inline fun <T> Sequence<T>.find(predicate: (T) -> Boolean): T? {     return firstOrNull(predicate) } 

(I'm not a Kotlin user myself, but I'm surprised that these methods are implemented as compile-time generated code manually defined for each collection type instead of as a single JVM generic method - is there some reason for this?)

like image 61
Dai Avatar answered Oct 02 '22 13:10

Dai