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

如何在JavaScript中实现Map的computeIfAbsent/getOrElseUpdate功能?

如何在JavaScript/TypeScript中实现Map的"获取或更新"逻辑?

问题背景

假设存在以下条件:

  • m 是一个 Map<number, V>(V为任意类型)
  • k 是一个 number 类型值

需要编写一个表达式,实现以下效果:

  • 要么获取键k对应的已存在的V类型值,
  • 要么创建一个新的v:V,将其存入Map的键k下,并返回该v

例如,SOME_EXPR(m, k, []) 需要在 m.get(k) 存在时返回该值,否则执行 m.set(k, []) 并返回 []。

具体示例

假设要逐步构建一个 Map<number, number[]>,为键48添加值100和200,为键52添加值300,按需创建空数组。需要类似 SOME_EXPR(map, key, value) 的表达式,使得执行:

var m = new Map(); // Map<number, number[]>
SOME_EXPR(m, 48, []).push(100)
SOME_EXPR(m, 48, []).push(200)
SOME_EXPR(m, 52, []).push(300)

后,Map变为:

{ 48 -> [100, 200]; 52 -> [300] }

那么应该用什么替代 SOME_EXPR?

已尝试方案

辅助函数方案

可以创建一个辅助方法:

function getOrElseUpdate(m, k, defaultValue) {
  if (!m.has(k)) {
    m.set(k, defaultValue);
  }
  return m.get(k);
}

然后用 getOrElseUpdate(m, k, []) 替代 SOME_EXPR,但该方法需要三次计算哈希值,且维护时需跳转查看函数定义,不够直观。

内联表达式方案

尝试内联实现:

SOME_EXPR(m,k,v) := ((k) => (m.get(k) || ((v) => (m.set(k, v), v))(v)))(k)

对应示例代码变为:

var m = new Map();
((k) => (m.get(k) || ((v) => (m.set(k, v), v))([])))(42).push(100);
((k) => (m.get(k) || ((v) => (m.set(k, v), v))([])))(42).push(200);
((k) => (m.get(k) || ((v) => (m.set(k, v), v))([])))(58).push(300);

该方案可行,但写法怪异,可读性差。

现在希望找到符合JavaScript惯用写法的实现,最好能在TypeScript中良好类型化。

其他语言的参考实现

Scala

val m = HashMap.empty[Int, ListBuffer[Int]]
m.getOrElseUpdate(48, ListBuffer.empty) += 100
m.getOrElseUpdate(48, ListBuffer.empty) += 200
m.getOrElseUpdate(52, ListBuffer.empty) += 300

// m 现在为:
//
// HashMap(
//   48 -> ListBuffer(100, 200), 
//   52 -> ListBuffer(300)
// )

Java

HashMap<Integer, List<Integer>> m = new HashMap<>();
m.computeIfAbsent(42, k -> new LinkedList<>()).add(100);
m.computeIfAbsent(42, k -> new LinkedList<>()).add(200);
m.computeIfAbsent(58, k -> new LinkedList<>()).add(300);

// m = {58=[300], 42=[100, 200]}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 02:45:40