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

JavaScript系列(10)-- Map数据结构专题

JavaScript Map数据结构专题 🗺️

在前九篇文章中,我们探讨了JavaScript的语言特性、ECMAScript标准、引擎工作原理、数值类型、字符串处理、Symbol类型、Object高级特性、Array高级操作和Set数据结构。今天,让我们深入了解JavaScript中的Map数据结构。Map是ES6引入的一种新的键值对集合,它提供了比普通对象更强大和灵活的特性。

Map基础概念 🌟

💡 小知识:Map是一种键值对的集合,其中的键可以是任何类型(包括对象、函数等),这与普通对象只能使用字符串作为键的限制不同。Map还维护了键值对的插入顺序,这使得它在需要有序数据时特别有用。

Map的创建和基本操作 📊

// 1. Map的创建方式
function mapCreation() {
    // 空Map
    const map1 = new Map();
    
    // 从数组创建
    const map2 = new Map([
        ['key1', 'value1'],
        ['key2', 'value2']
    ]);
    
    // 从对象创建
    const obj = { name: '张三', age: 25 };
    const map3 = new Map(Object.entries(obj));
    
    // 从其他Map创建
    const map4 = new Map(map2);
    
    // 基本操作
    map1.set('key', 'value');     // 设置键值对
    map1.get('key');              // 获取值
    map1.has('key');             // 检查键是否存在
    map1.delete('key');          // 删除键值对
    map1.clear();                // 清空Map
    console.log(map1.size);      // 获取大小
}

// 2. Map的迭代
function mapIteration() {
    const map = new Map([
        ['name', '张三'],
        ['age', 25],
        ['city', '北京']
    ]);
    
    // forEach方法
    map.forEach((value, key, map) => {
        console.log(`${key}: ${value}`);
    });
    
    // for...of循环
    for (const [key, value] of map) {
        console.log(`${key}: ${value}`);
    }
    
    // 获取所有键
    const keys = [...map.keys()];
    
    // 获取所有值
    const values = [...map.values()];
    
    // 获取所有条目
    const entries = [...map.entries()];
}

// 3. Map的键比较
function mapKeyComparison() {
    const map = new Map();
    
    // NaN作为键
    map.set(NaN, 'value');
    map.set(NaN, 'new value');  // 会覆盖之前的值
    console.log(map.size);      // 1
    
    // +0和-0作为键
    map.set(+0, 'zero');
    map.set(-0, 'negative zero');  // 被视为相同的键
    console.log(map.size);         // 1
    
    // 对象作为键
    const obj1 = { id: 1 };
    const obj2 = { id: 1 };
    map.set(obj1, 'object 1');
    map.set(obj2, 'object 2');
    console.log(map.size);      // 2,不同对象被视为不同的键
}

Map的高级操作 🔧

// 1. Map与对象的转换
class MapObjectConverter {
    // Map转对象
    static mapToObject(map) {
        const obj = {};
        for (const [key, value] of map) {
            if (typeof key === 'string' || 
                typeof key === 'number' || 
                typeof key === 'symbol') {
                obj[key] = value;
            }
        }
        return obj;
    }
    
    // 对象转Map
    static objectToMap(obj) {
        return new Map(Object.entries(obj));
    }
    
    // 深度转换
    static deepMapToObject(map) {
        const obj = {};
        for (const [key, value] of map) {
            if (typeof key === 'string' || 
                typeof key === 'number' || 
                typeof key === 'symbol') {
                obj[key] = value instanceof Map 
                    ? this.deepMapToObject(value) 
                    : value;
            }
        }
        return obj;
    }
}

// 2. Map的合并和分割
class MapOperations {
    // 合并Maps
    static merge(...maps) {
        const merged = new Map();
        for (const map of maps) {
            for (const [key, value] of map) {
                merged.set(key, value);
            }
        }
        return merged;
    }
    
    // 按条件分割Map
    static split(map, predicate) {
        const matched = new Map();
        const unmatched = new Map();
        
        for (const [key, value] of map) {
            if (predicate(key, value)) {
                matched.set(key, value);
            } else {
                unmatched.set(key, value);
            }
        }
        
        return [matched, unmatched];
    }
    
    // 过滤Map
    static filter(map, predicate) {
        const filtered = new Map();
        for (const [key, value] of map) {
            if (predicate(key, value)) {
                filtered.set(key, value);
            }
        }
        return filtered;
    }
}

// 3. Map的函数式操作
class FunctionalMapOperations {
    // Map
    static map(map, transform) {
        const result = new Map();
        for (const [key, value] of map) {
            result.set(key, transform(value, key));
        }
        return result;
    }
    
    // Reduce
    static reduce(map, reducer, initialValue) {
        let accumulator = initialValue;
        for (const [key, value] of map) {
            accumulator = reducer(accumulator, value, key);
        }
        return accumulator;
    }
    
    // Chain operations
    static chain(map) {
        return {
            map: transform => FunctionalMapOperations.chain(
                FunctionalMapOperations.map(map, transform)
            ),
            filter: predicate => FunctionalMapOperations.chain(
                MapOperations.filter(map, predicate)
            ),
            value: () => map
        };
    }
}

Map的实际应用 💼

让我们看看Map在实际开发中的一些应用场景:

// 1. 缓存系统
class AdvancedCache {
    constructor(maxSize = 1000, maxAge = 3600000) {
        this.cache = new Map();
        this.maxSize = maxSize;
        this.maxAge = maxAge;
    }
    
    set(key, value, ttl = this.maxAge) {
        if (this.cache.size >= this.maxSize) {
            const oldestKey = this.cache.keys().next().value;
            this.cache.delete(oldestKey);
        }
        
        this.cache.set(key, {
            value,
            timestamp: Date.now(),
            ttl
        });
    }
    
    get(key) {
        const item = this.cache.get(key);
        if (!item) return null;
        
        if (Date.now() - item.timestamp > item.ttl) {
            this.cache.delete(key);
            return null;
        }
        
        return item.value;
    }
    
    cleanup() {
        const now = Date.now();
        for (const [key, item] of this.cache) {
            if (now - item.timestamp > item.ttl) {
                this.cache.delete(key);
            }
        }
    }
}

// 2. 状态管理系统
class StateManager {
    constructor() {
        this.states = new Map();
        this.listeners = new Map();
    }
    
    setState(key, value) {
        const oldValue = this.states.get(key);
        this.states.set(key, value);
        
        // 通知监听器
        if (this.listeners.has(key)) {
            this.listeners.get(key).forEach(listener => 
                listener(value, oldValue)
            );
        }
    }
    
    getState(key) {
        return this.states.get(key);
    }
    
    subscribe(key, listener) {
        if (!this.listeners.has(key)) {
            this.listeners.set(key, new Set());
        }
        this.listeners.get(key).add(listener);
        
        // 返回取消订阅函数
        return () => {
            this.listeners.get(key).delete(listener);
        };
    }
}

// 3. 依赖注入容器
class DIContainer {
    constructor() {
        this.services = new Map();
        this.singletons = new Map();
    }
    
    register(name, constructor, dependencies = []) {
        this.services.set(name, { constructor, dependencies });
    }
    
    registerSingleton(name, constructor, dependencies = []) {
        this.register(name, constructor, dependencies);
        this.singletons.set(name, null);
    }
    
    resolve(name) {
        const service = this.services.get(name);
        if (!service) {
            throw new Error(`Service ${name} not found`);
        }
        
        // 检查是否是单例
        if (this.singletons.has(name)) {
            if (this.singletons.get(name) === null) {
                const instance = this.createInstance(service);
                this.singletons.set(name, instance);
            }
            return this.singletons.get(name);
        }
        
        return this.createInstance(service);
    }
    
    createInstance(service) {
        const dependencies = service.dependencies.map(dep => 
            this.resolve(dep)
        );
        return new service.constructor(...dependencies);
    }
}

性能优化 ⚡

处理Map时的一些性能优化技巧:

// 1. Map大小优化
function mapSizeOptimization() {
    // 预分配合适的大小
    const entries = new Array(1000)
        .fill(0)
        .map((_, i) => [`key${i}`, i]);
    
    // 一次性创建Map
    const map = new Map(entries);  // 比循环添加更快
    
    // 避免频繁修改
    const tempEntries = [];
    for (let i = 0; i < 1000; i++) {
        tempEntries.push([`key${i}`, i]);
    }
    const map2 = new Map(tempEntries);
}

// 2. Map操作优化
class OptimizedMapOperations {
    // 批量设置优化
    static batchSet(map, entries) {
        const newMap = new Map(map);
        for (const [key, value] of entries) {
            newMap.set(key, value);
        }
        return newMap;
    }
    
    // 批量删除优化
    static batchDelete(map, keys) {
        const newMap = new Map(map);
        for (const key of keys) {
            newMap.delete(key);
        }
        return newMap;
    }
}

// 3. 内存优化
class MemoryEfficientMap {
    constructor() {
        this.map = new Map();
        this.weakRefs = new WeakMap();
    }
    
    set(key, value) {
        if (typeof key === 'object' && key !== null) {
            const ref = new WeakRef(key);
            this.weakRefs.set(key, ref);
            this.map.set(ref, value);
        } else {
            this.map.set(key, value);
        }
    }
    
    get(key) {
        if (typeof key === 'object' && key !== null) {
            const ref = this.weakRefs.get(key);
            return ref ? this.map.get(ref) : undefined;
        }
        return this.map.get(key);
    }
}

最佳实践建议 💡

  1. Map使用场景
// 1. 键值对管理
function keyValueManagement() {
    // 使用对象作为键
    const userMap = new Map();
    const userObj = { id: 1, name: '张三' };
    userMap.set(userObj, { role: 'admin' });
    
    // 频繁增删键值对
    const cacheMap = new Map();
    cacheMap.set('key1', 'value1');
    cacheMap.delete('key1');
    
    // 需要保持插入顺序
    const orderedMap = new Map([
        [1, 'first'],
        [2, 'second'],
        [3, 'third']
    ]);
}

// 2. 数据关联
function dataAssociation() {
    const users = new Map();
    const posts = new Map();
    
    // 用户-帖子关联
    function associateUserPosts(userId, postId) {
        const userPosts = users.get(userId) || new Set();
        userPosts.add(postId);
        users.set(userId, userPosts);
    }
}

// 3. 状态追踪
function stateTracking() {
    const stateMap = new Map();
    
    function updateState(key, newState) {
        const oldState = stateMap.get(key);
        stateMap.set(key, newState);
        return [oldState, newState];
    }
}
  1. 错误处理和验证
// 1. Map验证
function validateMap(map) {
    if (!(map instanceof Map)) {
        throw new TypeError('参数必须是Map类型');
    }
    
    if (map.size === 0) {
        throw new Error('Map不能为空');
    }
    
    return true;
}

// 2. 安全的Map操作
function safeMapOperations() {
    function safeGet(map, key, defaultValue = null) {
        try {
            return map.has(key) ? map.get(key) : defaultValue;
        } catch (error) {
            console.error('获取值失败:', error);
            return defaultValue;
        }
    }
    
    function safeSet(map, key, value) {
        try {
            map.set(key, value);
            return true;
        } catch (error) {
            console.error('设置值失败:', error);
            return false;
        }
    }
}

// 3. 类型检查
function mapTypeChecking() {
    function isStringKeyMap(map) {
        return map instanceof Map && 
               [...map.keys()].every(key => typeof key === 'string');
    }
    
    function isObjectValueMap(map) {
        return map instanceof Map && 
               [...map.values()].every(value => 
                   value && typeof value === 'object'
               );
    }
}

结语 📝

JavaScript的Map数据结构为我们提供了一种强大的键值对存储方案。我们学习了:

  1. Map的基本概念和操作
  2. Map的高级操作和转换
  3. 实际应用场景
  4. 性能优化技巧
  5. 最佳实践和注意事项

💡 学习建议:在选择使用Map还是普通对象时,要考虑具体的使用场景。如果需要非字符串类型的键、需要保持插入顺序,或者需要频繁增删键值对,Map是更好的选择。同时,要注意Map的内存使用和性能优化。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻


http://www.kler.cn/a/488445.html

相关文章:

  • PLC实现HTTP协议JSON格式数据上报对接的参数配置说明
  • 微信小程序实现长按录音,点击播放等功能,CSS实现语音录制动画效果
  • 00000008_C并发编程与多线程
  • 反规范化带来的数据不一致问题的解决方案
  • 晨辉面试抽签和评分管理系统之一:考生信息管理和编排
  • MakeFile使用指南
  • 如何确保获取的淘宝详情页数据的准确性和时效性?
  • 基于Ubuntu2404脚本搭建openstackC版-ovn网络驱动
  • 设计模式 创建型 抽象工厂模式(Abstract Factory)与 常见技术框架应用 解析
  • Win32汇编学习笔记06.APIHook
  • 单片机 期末笔记
  • 《探秘鸿蒙NEXT中的人工智能核心架构》
  • 【2025 Rust学习 --- 11 实用工具特型01】
  • 车载音频开发(二):对音频数据作音量调节
  • Java 基于微信小程序的高校科研团队管理系统设计与实现(附源码,部署,文档
  • PHP RCE
  • JS爬虫实战演练
  • js观察者模式
  • nginx反向代理和负载均衡的区别
  • 【LeetCode】303. 区域和检索 - 数组不可变
  • linux 设置mysql 外网访问
  • 微信原生小程序自定义封装组件(以导航navbar为例)
  • 1.3作业
  • 机器学习的基本原理和算法
  • 缓存-Redis-API-Redisson-可重试
  • OpenCV轮廓相关操作API (C++)