跳转到主要内容

BiDirectionalMap

双向映射(BiMap)维护键和值之间的一对一映射关系,允许在两个方向上进行高效的 O(1) 查找。

安装

npm install @msnkr/data-structures

使用方法

import { BiDirectionalMap } from '@msnkr/data-structures';

const biMap = new BiDirectionalMap<string, number>();

API 参考

属性

  • size: number - 映射中键值对的数量

方法

设置和获取元素

// 设置键值对 - O(1)
biMap.set('one', 1);

// 通过键获取值 - O(1)
const value = biMap.get('one');

// 通过值获取键 - O(1)
const key = biMap.getKey(1);
双向查找

与普通映射不同,BiMap 允许通过值高效地查找键,时间复杂度为 O(1)。

检查存在性

// 检查键是否存在 - O(1)
const hasKey = biMap.hasKey('one');

// 检查值是否存在 - O(1)
const hasValue = biMap.hasValue(1);

删除元素

// 通过键删除 - O(1)
const removedByKey = biMap.deleteKey('one');

// 通过值删除 - O(1)
const removedByValue = biMap.deleteValue(1);

// 删除所有映射 - O(1)
biMap.clear();

迭代

// 迭代所有键
for (const key of biMap.keys()) {
console.log(key);
}

// 迭代所有值
for (const value of biMap.values()) {
console.log(value);
}

// 迭代所有条目
for (const [key, value] of biMap.entries()) {
console.log(`${key} => ${value}`);
}

// 使用 forEach
biMap.forEach((value, key, map) => {
console.log(`${key} 映射到 ${value}`);
});

实用方法

// 从条目创建 - O(n)
const entries: [string, number][] = [
['one', 1],
['two', 2],
];
const biMap = BiDirectionalMap.fromEntries(entries);

// 转换为对象 - O(n)
const obj = biMap.toObject();

示例

基本使用

const biMap = new BiDirectionalMap<string, number>();

// 设置映射(支持链式调用)
biMap.set('one', 1).set('two', 2).set('three', 3);

// 双向查找
console.log(biMap.get('one')); // 1
console.log(biMap.getKey(2)); // "two"

console.log(biMap.hasKey('three')); // true
console.log(biMap.hasValue(1)); // true

HTTP 状态码映射

const statusCodes = new BiDirectionalMap<number, string>();

statusCodes.set(200, 'OK');
statusCodes.set(404, 'Not Found');
statusCodes.set(500, 'Internal Server Error');

// 通过代码查找
console.log(statusCodes.get(404)); // "Not Found"

// 通过消息查找
console.log(statusCodes.getKey('OK')); // 200

国家代码注册表

const countryCodes = new BiDirectionalMap<string, string>();

countryCodes.set('US', 'United States');
countryCodes.set('GB', 'United Kingdom');
countryCodes.set('FR', 'France');

// 通过代码获取国家名称
console.log(countryCodes.get('US')); // "United States"

// 通过名称获取国家代码
console.log(countryCodes.getKey('France')); // "FR"

处理重复值(一对一约束)

const biMap = new BiDirectionalMap<string, number>();

biMap.set('one', 1);
biMap.set('another', 1); // 覆盖之前的映射

console.log(biMap.get('one')); // undefined(映射已删除)
console.log(biMap.get('another')); // 1
console.log(biMap.getKey(1)); // "another"

console.log(biMap.size); // 1(只存在一个映射)
一对一约束

BiMap 强制执行一对一映射。使用已存在的值设置键会删除之前的键值对。

用户 ID 到用户名映射

const userRegistry = new BiDirectionalMap<number, string>();

// 注册用户
userRegistry.set(1, 'alice');
userRegistry.set(2, 'bob');
userRegistry.set(3, 'charlie');

// 通过 ID 查找用户名
const username = userRegistry.get(2); // "bob"

// 通过用户名查找 ID
const userId = userRegistry.getKey('alice'); // 1

// 检查用户名是否已被占用
if (userRegistry.hasValue('newuser')) {
console.log('用户名已被占用!');
}

语言翻译

const translations = new BiDirectionalMap<string, string>();

translations.set('hello', '你好');
translations.set('goodbye', '再见');
translations.set('thank you', '谢谢');

// 英译中
console.log(translations.get('hello')); // "你好"

// 中译英
console.log(translations.getKey('再见')); // "goodbye"

时间复杂度

操作平均最坏
setO(1)O(1)
getO(1)O(1)
getKeyO(1)O(1)
hasKeyO(1)O(1)
hasValueO(1)O(1)
deleteKeyO(1)O(1)
deleteValueO(1)O(1)
clearO(1)O(1)

最佳实践

何时使用 BiMap

  • ✅ 需要双向查找(键到值和值到键)
  • ✅ 键和值之间是一对一关系
  • ✅ 需要频繁的反向查找操作
  • ✅ 维护唯一标识符映射

何时不使用 BiMap

  • ❌ 一个键可能对应多个值
  • ❌ 只需要单向查找
  • ❌ 值不需要是唯一的

相关数据结构

  • Map - 单向键值映射,支持重复值
  • Set - 唯一值集合,不支持键值对
  • SortedMap - 按键排序的映射

TypeScript 提示

// 使用泛型确保类型安全
const stringToNumber = new BiDirectionalMap<string, number>();
stringToNumber.set('one', 1);

// 类型检查
const value: number | undefined = stringToNumber.get('one');
const key: string | undefined = stringToNumber.getKey(1);

// 接口支持
interface User {
id: number;
username: string;
}

const userMap = new BiDirectionalMap<number, User>();
userMap.set(1, { id: 1, username: 'alice' });