Suppose I have a List<Animal>, and I want to find the first Dog in it. I then want to access some Dog-specific properties of the found Dog.
find doesn't really work:
val dog = animals.find { it is Dog }
// dog is of type "Animal?", but I want "Dog?"
I could use filterIsInstance:
val dog = animals.filterIsInstance<Dog>().firstOrNull()
But that goes through the whole animal list. I want it to stop when it finds the first dog. What is a built in method that does this?
CodePudding user response:
You can use sequences for lazy evaluations
Compare following code samples:
Eager
val firstString = listOf(1, "2", 3, "4", 5, "6")
// following operations are applied to List
.filterIsInstance<String>()
.onEach { println(it) }
.firstOrNull()
println("Result: $firstString")
Output:
2
4
6
Result: 2
Lazy
val firstString = listOf(1, "2", 3, "4", 5, "6")
.asSequence()
// following operations are applied to Sequence
.filterIsInstance<String>()
.onEach { println(it) }
.firstOrNull()
println("Result: $firstString")
Output:
2
Result: 2
In both cases result is the same, but for lazy case no further steps are made after first match is found.
CodePudding user response:
You can use firstNotNullOfOrNull (which is a mouthful to say :D), with as? instead of is.
val dog = animals.firstNotNullOfOrNull { it as? Dog }
It applies the transformation to each element, and returns the first not-null transformation result, or null if there is no such result.
There is also the counterpart firstNotNullOf that throws an exception when there are no not-null results.
