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

如何更新含多层嵌套不可变对象的Java Map中的值?

嵌套不可变Java Map的替换值解决方案

我有一个从JSON反序列化得到的Java Map,包含多层嵌套的不可变对象。另有一个存储部分字符串替代值的Map,该Map通过在键后追加原始值来区分数组中的不同元素。希望用第二个Map中的值替换第一个Map的对应值,以下是可行的解决思路:

原始Map

{
  "product": "Internet",
  "version": 3.1,
  "releaseDate": "2014-06-25T00:00:00.000Z",
  "person": {
    "id": 12345,
    "name": "John Doe",
    "phones": {
      "home": "800-123-4567",
      "mobile": "877-123-1234"
    },
    "email": [
      "jd@example.com",
      "jd@example.org"
    ],
    "dateOfBirth": "1980-01-02T00:00:00.000Z",
    "registered": true,
    "emergencyContacts": [
      {
        "name": "Jane Doe",
        "phone": "888-555-1212",
        "relationship": "spouse"
      },
      {
        "name": "Justin Doe",
        "phone": "877-123-1212",
        "relationship": "parent"
      }
    ]
  }
}

存储替代值的Map

{
  "product": "Strong Internet",
  "person.name=John Doe" : "Barry Richards",
  "person.emergencyContacts.name=Jane Doe" : "Jane Richards"
}

期望结果Map

{
  "product": "Strong Internet",
  "version": 3.1,
  "releaseDate": "2014-06-25T00:00:00.000Z",
  "person": {
    "id": 12345,
    "name": "Barry Richards",
    "phones": {
      "home": "800-123-4567",
      "mobile": "877-123-1234"
    },
    "email": [
      "jd@example.com",
      "jd@example.org"
    ],
    "dateOfBirth": "1980-01-02T00:00:00.000Z",
    "registered": true,
    "emergencyContacts": [
      {
        "name": "Jane Richards",
        "phone": "888-555-1212",
        "relationship": "spouse"
      },
      {
        "name": "Justin Doe",
        "phone": "877-123-1212",
        "relationship": "parent"
      }
    ]
  }
}

可行解决思路

1. 解析替换规则的键格式

先对替换Map中的每个键做拆分处理:

  • 普通键(如product):直接对应原始Map的顶级键,找到后直接替换值。
  • 带=的键(如person.name=John Doe):拆分为路径部分(person.name)和匹配条件(John Doe)——先通过路径定位到原始Map中的目标字段,再验证该字段的原始值是否与匹配条件一致,一致则替换。
  • 数组嵌套的键(如person.emergencyContacts.name=Jane Doe):路径包含数组层级,需要先遍历emergencyContacts数组中的每个对象,找到name字段等于Jane Doe的元素,再替换该元素的name值。

2. 递归遍历+创建新对象处理不可变特性

由于原始对象是不可变的,不能直接修改,必须通过创建新的Map/对象来保存修改后的数据:

  • 遍历原始Map的键值对,基础类型值(字符串、数字、布尔等)直接检查是否有匹配的替换规则,有则用新值,无则保留。
  • 遇到嵌套Map(如person),递归处理该子Map,生成修改后的新子Map,再替换到顶级Map中。
  • 遇到数组(如emergencyContacts):遍历数组每个元素,若为对象类型则递归处理,结合匹配条件找到需要修改的元素,创建该元素的新副本并替换目标字段,非目标元素直接保留。

3. 具体实现步骤

  • 键拆分工具方法:写方法将替换键拆分为路径数组和匹配值,比如把person.emergencyContacts.name=Jane Doe拆成["person", "emergencyContacts", "name"]和Jane Doe。
  • 目标位置定位:根据路径数组遍历原始Map,遇到数组时遍历所有元素,检查元素对应字段是否匹配条件,找到需要修改的目标元素。
  • 生成不可变新对象:对于需要修改的嵌套Map或数组元素,创建新的实例,复制原有所有字段,仅替换目标字段的值。
  • 整合结果:将所有修改后的部分组合成新的顶级Map,得到最终结果。

4. 注意事项

  • 不可变对象必须通过新实例替换,不能尝试修改原对象,否则会抛出UnsupportedOperationException。
  • 明确数组匹配规则:是替换所有符合条件的元素,还是仅第一个。
  • 路径解析要兼容多层嵌套、Map与数组混合的复杂结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:50:31