当前位置: 首页 > news >正文

Kotlin × Gson:为什么遍历 JsonObject 要用 entrySet()

理解 entrySet() 和 keySet() 的区别,掌握高效遍历与 JSON 合并技巧。

一、前言

在日常 Android 或 Kotlin 后端开发中,我们经常需要操作 JSON 对象,例如:

val mergedData = JsonObject().apply {originalMessageObject.entrySet().forEach { entry ->add(entry.key, entry.value)}route.extraData?.entrySet()?.forEach { entry ->add(entry.key, entry.value)}
}

很多同学会问:

为什么这里要用 .entrySet()?我直接 .keySet() 不行吗?

别看这只是一个小细节,但它直接影响性能、语义清晰度,以及你代码的“专业感”。
这篇文章我们就来彻底讲清楚。

二、Map / JsonObject 的三种遍历方式

Gson 的 JsonObject 本质上是一个 Map<String, JsonElement>,因此遍历方式和 Map 一样:

遍历方式能拿到什么性能适用场景
keySet()只能拿到 key⚠️ 需要再 get(key) 查一次 value只需要 key 时
values()只能拿到 value✅ 一次遍历只需要 value 时
entrySet()一次拿到 key + value✅ 高效 + 清晰同时需要 key 与 value 时(最常用)

三、为什么 entrySet() 更推荐

1. 一次遍历同时拿 key 与 value

entrySet() 返回 Set<Map.Entry<K, V>>
每个 entry 里已经包含 key 和 value,不需要再调用 get(key)

// ✅ 推荐:一次拿到 key + value
for ((key, value) in json.entrySet()) {merged.add(key, value)
}// ❌ 不优:keySet + get(key),多一次查找
for (key in json.keySet()) {val value = json.get(key)merged.add(key, value)
}

虽然对小对象差别不大,但在大 JSON、频繁合并的场景下,多余的 get() 会产生上百次额外查表操作。

2. Kotlin 写法更优雅

Kotlin 支持对 Map.Entry 解构,因此:

for ((key, value) in json.entrySet()) {println("$key = $value")
}

写法简洁直观,语义完全贴合“我在遍历键值对”的需求。

3. 性能对比(复杂度分析)

假设对象有 n 个字段:

操作时间复杂度说明
entrySet()O(n)每次直接拿 key,value
keySet()+get(key)O(n) + n×O(1)多执行一次查找,哈希表仍有额外开销

在 HashMap 这种结构中,虽然 get() 平均是 O(1),但每次都要进行哈希、比较、寻址操作。
对性能敏感的代码(如 TCP 消息解析、日志聚合)中,entrySet() 明显更合适。

四、JSON 合并的最佳实践

合并两个 JsonObject 是最常见的场景,比如 “原始消息 + 附加数据”:

val merged = JsonObject().apply {// 先复制原始对象for ((k, v) in original.entrySet()) add(k, v)// 再复制 extraData(同名 key 覆盖)for ((k, v) in extra.entrySet()) add(k, v)
}

如果希望“原始字段优先、extra 只补充缺失”:

val merged = JsonObject().apply {for ((k, v) in original.entrySet()) add(k, v)for ((k, v) in extra.entrySet()) if (!has(k)) add(k, v)
}

递归深度合并(嵌套对象)也同样基于 entrySet()

fun mergeDeep(dst: JsonObject, src: JsonObject) {for ((k, v) in src.entrySet()) {val dv = dst.get(k)if (dv is JsonObject && v is JsonObject) mergeDeep(dv, v)else dst.add(k, v.deepCopy())}
}

五、什么时候用 keySet()

只有一种情况:你根本不需要 value。

for (key in json.keySet()) {if (key.startsWith("_")) println("非法字段:$key")
}

或者做键集合的运算(交集、差集等)时。

只要你需要 value,首选 entrySet()。
只要你不需要 value,用 keySet() 更干净。

六、实践建议

  1. 固定习惯:遍历 Map/Json 时默认用 entrySet()

  2. 明确策略:合并时清楚覆盖逻辑(覆盖/补齐/深度合并)。

  3. 必要时深拷贝:避免 JsonElement 共享引用。

  4. 日志友好:当字段被覆盖时可打印提示,便于调试。

七、总结记忆表

目的推荐写法说明
遍历所有字段for ((k, v) in json.entrySet())最常见用法
只看 keyfor (k in json.keySet())只需键名时
只看 valuefor (v in json.values())只需值时
复制对象dst.add(k, v)后写覆盖前写
保留原始if (!dst.has(k)) dst.add(k, v)

只补充缺失字段

八、一句话总结

entrySet() = 一次拿到 key + value(高效遍历)
keySet() = 只拿 key(轻量但功能有限)

✅ “需要键和值,就用 entrySet;只要键,用 keySet。”

—— 这就是高质量 Kotlin JSON 代码的底层逻辑。

http://www.dtcms.com/a/524862.html

相关文章:

  • 中国建设安全监理协会网站年轻的儿媳
  • 网站网站到底怎么做个人代运营一般怎么收费
  • segformer算法——Mix-FFN详细讲解
  • 高精度算法全解析:从原理到实现
  • 参考线模块(上)
  • 鸿蒙Next图片开发指南:从解码、处理到接收的完整实践
  • 2025年第六届MathorCup大数据竞赛B题超详细解题思路
  • How to Write Hotkeys(如何编写热键)
  • 基于python语音信号的抑郁症识别模型设计与应用
  • 基于python语音信号的呼吸道疾病诊断模型设计
  • 西城网站建设余姚电商交易网站建设
  • 【交换机工作原理深度解析:从基础架构到前沿技术】
  • 学校培训网站建设网页设计师培训无锡
  • 「用Python来学微积分」12. 无穷小量和无穷大量
  • Elasticsearch从入门到进阶——搜索优化原理
  • 农田、果园与灌区气象监测的技术应用与实践价值
  • php做网站好吗wordpress博客非插件
  • 继承(2),咕咕咕!
  • C++编程技巧和规范_9_引用计数解析
  • android11禁止安装apk
  • 深入了解linux网络—— 自定义协议(下)
  • 金麦建站官网成都视频剪辑培训
  • 【C++闯关笔记】详解多态
  • 数据库技术指南(二):MySQL CURD 与高级查询实战
  • 用mvc做网站报告做做做网站
  • 设置一个自定义名称的密钥,用于 git 仓库上下传使用
  • MAC Flood与ARP Flood攻击区别详解
  • 高兼容与超低延迟:互联网直播点播平台EasyDSS直播服务如何成为直播点播应用的“技术底座”?
  • MongoDB 集群优化实战指南
  • wordpress网站速度检测医院做网站需要多少钱