如何创建以整数对为键的JavaScript Map?
JavaScript Map 整数键的无字符串转换解决方案
问题背景
JavaScript的Map采用引用比较来判断对象键是否相等,这意味着直接使用数组(比如[number, number])作为键会失效:
const map = new Map(); const coordinates = [1, 3]; map.set(coordinates, 0); map.get([1, 3]); // 返回 undefined
常见的解决办法是将键拼接为字符串(如${a}_${b}),但这种方法需要进行数字转字符串操作。如果已知整数范围,还可以用位运算(a << 8) + b提升性能,但这种方法受限于数值范围。
那么对于范围未知的整数,有没有无需字符串转换、又能保证键唯一性的类似方案?
可行方案
1. 利用BigInt进行数值拼接
BigInt支持任意精度的整数运算,我们可以将其中一个整数左移足够多的位数(比如64位,覆盖绝大多数常规整数场景),再和另一个整数的BigInt形式进行组合,生成唯一的BigInt键:
function generateKey(a, b) { return (BigInt(a) << 64n) | BigInt(b); } // 使用示例 const map = new Map(); map.set(generateKey(1, 3), 0); console.log(map.get(generateKey(1, 3))); // 输出 0
这种方法全程都是数值运算,没有字符串转换,且不会出现溢出问题,能保证任意范围整数组合的键唯一性。
2. 复用对象引用的缓存池
如果坚持使用对象作为键,可以创建一个缓存池,确保相同数值组合的对象始终返回同一个引用:
const keyCache = new Map(); function getUniqueKey(a, b) { // 用BigInt生成缓存键,避免字符串转换 const cacheKey = (BigInt(a) << 64n) | BigInt(b); if (!keyCache.has(cacheKey)) { keyCache.set(cacheKey, [a, b]); } return keyCache.get(cacheKey); } // 使用示例 const map = new Map(); map.set(getUniqueKey(1, 3), 0); console.log(map.get(getUniqueKey(1, 3))); // 输出 0
这里缓存池的内部键用BigInt生成,避免了字符串转换,同时确保存入Map的是同一个引用,解决了引用比较的问题。
3. 封装元组类并复用实例
可以封装一个元组类,通过静态方法复用相同数值组合的实例,本质和缓存池思路一致,但结构更清晰:
class IntTuple { constructor(a, b) { this.a = a; this.b = b; } static get(a, b) { const cacheKey = (BigInt(a) << 64n) | BigInt(b); if (!IntTuple.cache.has(cacheKey)) { IntTuple.cache.set(cacheKey, new IntTuple(a, b)); } return IntTuple.cache.get(cacheKey); } } IntTuple.cache = new Map(); // 使用示例 const map = new Map(); map.set(IntTuple.get(1, 3), 0); console.log(map.get(IntTuple.get(1, 3))); // 输出 0
内容的提问来源于stack exchange,提问作者Kaia
相关产品推荐
相关产品推荐

