Kotlin:遍历过滤后的(可能为空且最多一个元素)列表

Kotlin: looping through a filtered (possibly empty and at most one element) list

我有一个风暴螺栓,它获取包含类型 MyClass 的值的元组,该值又带有时间字段 startTime。在 bolt 的最后,我想记录处理从一开始所花费的时间(标记为 startTime)。所以我可以这样做:

override fun doExecute(input: Tuple): Boolean {
    ... // my processing logic
    input.values.filterIsInstance(MyClass).forEach {
        val endToEndTime = (System.currentTimeMillis() - it.startTime).toInt()
        stats.recordExecutionTime("mytag", endToEndTime)
    }
} 

我对这种方法没有任何问题。就外观而言,看起来我可以在元组中有多个 MyClass 实例(我没有)。所以我在想我是否可以从列表中选择第一个:

override fun doExecute(input: Tuple): Boolean {
    ... // my processing logic
    input.values.filterIsInstance(MyClass).first().let {
        val endToEndTime = (System.currentTimeMillis() - it.startTime).toInt()
        stats.recordExecutionTime("mytag", endToEndTime)
    }
} 

这似乎更具可读性。但是,如果 filterIsInstance(MyClass) 调用 returns 一个空列表,我会通过调用 first 得到一个异常,而第一个解决方案没有任何异常。由于这是纯粹的日志记录目的,我希望它没有异常。

有更好的方法吗?

有更好的办法! :)

您可以使用firstOrNull()然后安全调用:

input.values.filterIsInstance(MyClass).firstOrNull()?.let {
    val endToEndTime = (System.currentTimeMillis() - it.startTime).toInt()
    stats.recordExecutionTime("mytag", endToEndTime)
}

您还可以将 filterIsInstance 调用替换为带有谓词的 firstOrNull() 版本,如下所示:

input.values.firstOrNull { it is MyClass }?.let {ű
    it as MyClass
    val endToEndTime = (System.currentTimeMillis() - it.startTime).toInt()
    stats.recordExecutionTime("mytag", endToEndTime)
}