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

Kotlin中如何高效切片vararg参数?

Kotlin嵌套JSON对象扩展函数的vararg参数优化方案

问题描述

我编写了一个扩展函数,用于根据名称获取JSON对象的元素:

fun JSONObject.obj (name: String): JSONObject? =
    try { this.getJSONObject(name) }
    catch (e: JSONException) { null }

现在想将其扩展到嵌套JSON对象,于是编写了以下代码:

tailrec fun JSONObject.obj (first: String, vararg rest: String): JSONObject? =
    if (rest.size == 0)
        obj(first)
    else
        obj(first)?.obj(rest[0], *rest.drop(1).toTypedArray())

但这段代码效率很低,请问切片vararg参数的最优方法是什么?

优化方案

核心问题:避免频繁创建数组

当前实现每次递归都调用rest.drop(1).toTypedArray(),这会反复生成新数组,带来不必要的内存分配和GC开销。最优思路是直接操作原数组的索引,或者用循环替代递归,彻底避免数组切片操作。

方案1:索引式尾递归(保留尾递归特性)

重构为带索引参数的私有辅助函数,对外暴露的入口函数传递初始索引:

fun JSONObject.obj(vararg keys: String): JSONObject? {
    tailrec fun traverse(current: JSONObject?, index: Int): JSONObject? {
        if (index >= keys.size) return current
        val next = current?.obj(keys[index]) ?: return null
        return traverse(next, index + 1)
    }
    return traverse(this, 0)
}

如果要保留原函数“第一个参数单独、后续vararg”的结构,可以调整为:

tailrec fun JSONObject.obj(first: String, vararg rest: String): JSONObject? {
    val allKeys = arrayOf(first, *rest)
    tailrec fun traverse(current: JSONObject?, index: Int): JSONObject? {
        if (index >= allKeys.size) return current
        val next = current?.obj(allKeys[index]) ?: return null
        return traverse(next, index + 1)
    }
    return traverse(this, 0)
}

方案2:循环实现(性能最优)

直接用循环替代递归,逻辑更直观,且完全没有递归调用和数组切片的额外开销:

fun JSONObject.obj(vararg keys: String): JSONObject? {
    var current: JSONObject? = this
    for (key in keys) {
        current = current?.obj(key) ?: break
    }
    return current
}

优化效果说明

  • 两种方案都避免了原实现中反复创建数组的问题,大幅减少内存开销。
  • 循环实现的性能略优于尾递归(尽管Kotlin会把尾递归优化为循环,但循环写法本身更直接)。
  • 所有方案都保留了原函数的空安全特性,遇到不存在的键时直接返回null。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:10:39