Kotlin中高效查找嵌套列表外层列表目标元素最后出现索引的方法及问题排查
问题分析与解决方案
首先咱们得先搞清楚你代码里的问题出在哪:你用了flatMap { it.value },这一步把所有Group内部的GroupValue都展平成了一个连续的序列,相当于把嵌套列表变成了一维列表。然后你调用的indexOfLast是在这个扁平后的一维序列里找目标元素的索引,所以得到13是正常的——但这和你要找的「外层Group的最后一个符合条件的索引」完全不是一回事。
你的真实需求是:找到外层列表中最后一个包含至少一个isRead == false的GroupValue的Group的索引,对应你的示例里就是索引9的那个Group(因为它之后的Group10里所有元素都是已读的)。
正确实现代码
直接调整逻辑,不要展平列表,而是在外层列表上遍历判断每个Group是否符合条件:
fun main() { val value = listOf( Group(0, mutableListOf(GroupValue(true, "1"))), Group(1, mutableListOf(GroupValue(true, "2"))), Group(2, mutableListOf(GroupValue(false, "3"))), Group(3, mutableListOf(GroupValue(true, "4"))), Group(4, mutableListOf(GroupValue(false, "5"))), Group(5, mutableListOf(GroupValue(true, "6"))), Group(6, mutableListOf(GroupValue(true, "6"), GroupValue(false, "7"))), Group(7, mutableListOf(GroupValue(true, "6"), GroupValue(false, "7"))), Group(8, mutableListOf(GroupValue(true, "6"), GroupValue(true, "7"), GroupValue(false, "7"))), Group(9, mutableListOf(GroupValue(false, "6"), GroupValue(true, "7"))), Group(10, mutableListOf(GroupValue(true, "7"))) ) // 核心逻辑:直接在外层列表找最后一个包含未读元素的Group val result = value.indexOfLast { group -> // any()会在找到第一个符合条件的元素后立即停止遍历,效率很高 group.value.any { it?.isRead == false } } println("result $result") // 输出9,符合你的期望 } data class Group( val key: Int, val value: MutableList<GroupValue?> ) data class GroupValue( val isRead: Boolean? = null, val id: String? = null )
代码解释
indexOfLast直接作用于外层列表:这样返回的就是外层Group的索引,完全符合你的需求。- 用
any()判断内层条件:any()方法是短路遍历——只要找到第一个it?.isRead == false的元素就会停止,不需要遍历整个内层列表,效率比遍历全部元素更高。 - 可选优化:大数据量场景用序列:如果你的外层列表非常大,可以用
asSequence()做懒加载优化,避免创建不必要的中间集合:val result = value.asSequence().indexOfLast { group -> group.value.asSequence().any { it?.isRead == false } }
排查问题的思路
- 明确需求边界:先写清楚自己要的是「外层元素索引」还是「内层元素索引」,避免操作层级混淆。
- 检查中间操作的影响:
flatMap、flatten这类操作会改变数据结构,一定要确认后续操作是否基于改变后的结构。 - 打印中间结果调试:比如你可以先把
flatMap后的序列打印出来,就能看到它是一个包含14个元素的列表(数一下你的示例里所有内层元素总数),最后一个isRead == false的元素在第13位(索引从0开始),这样就能立刻明白为什么输出13了。
内容的提问来源于stack exchange,提问作者Vivek Modi
相关产品推荐
相关产品推荐

