如何在列表中找到特定类型的元素,并智能转换结果?

How can I find an element of a particular type in a list, and also smart cast the result?

假设我有一个List<Animal>,我想在其中找到第一个Dog。然后我想访问找到的 Dog.

的一些 Dog 特定属性

find 确实不行:

val dog = animals.find { it is Dog }
// dog is of type "Animal?", but I want "Dog?"

我可以使用 filterIsInstance:

val dog = animals.filterIsInstance<Dog>().firstOrNull()

但这遍及整个动物列表。我希望它在找到第一只狗时停止。执行此操作的内置方法是什么?

您可以使用 firstNotNullOfOrNull(说起来有点啰嗦 :D),用 as? 代替 is

val dog = animals.firstNotNullOfOrNull { it as? Dog }

它将转换应用于每个元素,returns 第一个 not-null 转换结果,如果没有这样的结果,则为 null。

还有对应的 firstNotNullOf 会在没有 not-null 结果时抛出异常。

您可以使用序列进行延迟计算

比较以下代码示例:

渴望

val firstString = listOf(1, "2", 3, "4", 5, "6")
        // following operations are applied to List
        .filterIsInstance<String>()
        .onEach { println(it) }
        .firstOrNull()

println("Result: $firstString")

输出:

2
4
6
Result: 2

懒惰

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")

输出:

2
Result: 2

这两种情况的结果是相同的,但对于懒惰的情况,在找到第一个匹配项后不会进行进一步的步骤。