如何在Kotlin Sequence中优先获取首个无效元素,否则返回末尾元素?
解决方案
咱们可以通过一次遍历序列同时完成两个需求,既不会重复消费序列,也不用把整个序列转成List占用额外内存。核心思路是用Kotlin的fold函数累积遍历过程中的状态:记录是否找到首个无效元素,以及当前遍历到的最后一个元素。
实现代码(用数据类更清晰)
// 定义数据类保存遍历状态 data class TraversalResult(val firstInvalid: Int?, val lastElement: Int) // 示例序列,实际可替换为任意有限的Sequence<Int> val seq = sequenceOf(1, 2, -3, 4, 5) val traversalResult = seq.fold(TraversalResult(null, 0)) { acc, current -> if (acc.firstInvalid != null) { // 已找到无效元素,后续仅更新最后一个元素 acc.copy(lastElement = current) } else { // 未找到无效元素,检查当前元素是否符合无效条件 if (current < 0) { TraversalResult(current, current) } else { TraversalResult(null, current) } } } // 最终取值:存在无效元素则取第一个,否则取最后一个元素 val finalValue = traversalResult.firstInvalid ?: traversalResult.lastElement
简化版(无需额外定义数据类)
如果不想新增数据类,直接用Pair存储状态也可以:
val seq = sequenceOf(1, 2, 3, 4, 5) // 无无效元素的示例 val (firstInvalid, lastElement) = seq.fold(Pair<Int?, Int>(null, 0)) { (invalid, last), current -> // 已找到无效元素时,仅更新最后一个元素 invalid?.let { Pair(it, current) } ?: run { // 未找到时,判断当前元素是否无效 if (current < 0) Pair(current, current) else Pair(null, current) } } val finalValue = firstInvalid ?: lastElement
逻辑说明
- 整个流程仅遍历序列一次,彻底解决了序列无法重复消费的问题。
fold的初始lastElement设为0只是占位,序列第一个元素会直接覆盖该值(因为序列是有限非空的)。- 一旦找到首个无效元素,后续遍历仅更新最后一个元素(其实也可以直接返回当前状态,不更新最后一个元素也不影响最终结果,只是保持流程统一)。
内容的提问来源于stack exchange,提问作者k314159
相关产品推荐
相关产品推荐

