You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中用函数式方式扁平化嵌套Role对象树获取全量角色列表

问题分析

原有代码存在以下核心问题:

  • 边界判断逻辑错误:rootRoles == null && roles == null && roles?.isEmpty() == true 是永假表达式,roles为null时不可能同时满足isEmpty() == true
  • 递归逻辑混乱:递归过程中重复拼接根角色列表,会产生大量重复数据
  • 空安全处理冗余:Person类的roles是Set类型非空,不需要额外传递空值
  • 缺少去重逻辑:嵌套层级中可能出现重复角色,未做去重处理会导致结果冗余
正确实现

方案1:扩展函数+递归实现(最简洁函数式风格)

给Role类扩展递归拉平方法,直接处理角色集合即可:

// 扩展方法:获取当前角色 + 所有嵌套子角色的平替列表
fun Role.flattenWithChildren(): List<Role> {
    val children = childrenRoles ?: emptyList()
    return listOf(this) + children.flatMap { it.flattenWithChildren() }
}

fun Person.resolveAllRoles(): List<Role> {
    return roles
        .flatMap { it.flattenWithChildren() }
        .distinctBy { it.id } // 按角色ID去重,避免不同路径返回相同角色
}

方案2:纯函数实现(无需扩展函数)

如果不想定义扩展函数,也可以用纯工具函数实现:

fun flattenAllRoles(roles: Collection<Role>): List<Role> {
    return roles.flatMap { role ->
        listOf(role) + (role.childrenRoles?.let { flattenAllRoles(it) } ?: emptyList())
    }.distinctBy { it.id }
}

fun resolve(rootPerson: Person): List<Role> {
    return flattenAllRoles(rootPerson.roles)
}

如果需要兼容入参为null的场景,可以调整函数签名:

fun flattenAllRoles(roles: Collection<Role>?): List<Role>? {
    return roles?.let {
        it.flatMap { role ->
            listOf(role) + (role.childrenRoles?.let { c -> flattenAllRoles(c) } ?: emptyList())
        }.distinctBy { it.id }
    }
}

方案3:尾递归实现(针对深嵌套场景)

如果角色嵌套层级很深(超过100层),可以用尾递归实现避免栈溢出:

tailrec fun flattenAllRolesTailRec(remaining: List<Role>, result: MutableSet<Role> = mutableSetOf()): List<Role> {
    if (remaining.isEmpty()) return result.toList()
    val current = remaining.first()
    result.add(current)
    val nextRemaining = remaining.drop(1) + (current.childrenRoles ?: emptyList())
    return flattenAllRolesTailRec(nextRemaining, result)
}

fun Person.resolveAllRoles(): List<Role> = flattenAllRolesTailRec(roles.toList())

内容的提问来源于stack exchange,提问作者SlandShow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 11:24:01