深度比较Map的遍历

在Java项目中,常常会涉及到Map的遍历。然而,不同的方式遍历Map时,效率是不一样的。我总结了一下,可能会有的4种方式来实现Map的遍历。

1.使用enrtySet()for each遍历

for (Map.Entry<String,Integer> entry : testMap.entrySet()) {
    //entry.getKey();
    //entry.getValue();
}

 
2. 使用keySet() for each 遍历

for (String key : testMap.keySet()) {
    //testMap.get(key);
}
3. 使用 enrtySet() 迭代遍历

Iterator<Map.Entry<String,Integer>> itr1 = testMap.entrySet().iterator();
while(itr1.hasNext()){
    Map.Entry<String,Integer> entry = itr1.next();
    //entry.getKey();
    //entry.getValue();
}
4. 使用 keySet()迭代遍历

Iterator itr2 = testMap.keySet().iterator();
while(itr2.hasNext())
{
    String key = itr2.next();
    testMap.get(key);
}

比较4种方式的性能。使用100万条数据填充一个Map对象,后遍历这个Map,比较遍历的时间花费。

public class ComparingMapLoop {
    private static int MAP_SIZE = 1000000;
    private static Map<String, Integer> testMap = new HashMap<String, Integer>(MAP_SIZE);

    static {
        for (int i = 0; i < MAP_SIZE; i++) {
            testMap.put("key_" + i, i);
        }
    }

    public void testMapLoop() {
        long startTime = Calendar.getInstance().getTimeInMillis();
        //First way using entrySet in for-each loop
        for (Map.Entry<String, Integer> entry : testMap.entrySet()) {
            entry.getKey();
            entry.getValue();
        }

        System.out.println("Using entrySet() in for-each loop : " + (Calendar.getInstance().getTimeInMillis() - startTime));

        startTime = Calendar.getInstance().getTimeInMillis();
        //Second way using keySet() in for-each loop
        for (String key : testMap.keySet()) {
            testMap.get(key);
        }

        System.out.println("Using keySet() in for-each loop : " + (Calendar.getInstance().getTimeInMillis() - startTime));

        startTime = Calendar.getInstance().getTimeInMillis();
        //Third way using Iterator on entrySet() in while loop
        Iterator<Map.Entry<String, Integer>> itr1 = testMap.entrySet().iterator();
        while (itr1.hasNext()) {
            Map.Entry<String, Integer> entry = itr1.next();
            entry.getKey();
            entry.getValue();
        }

        System.out.println("Using entrySet() and iterator : " + (Calendar.getInstance().getTimeInMillis() - startTime));

        startTime = Calendar.getInstance().getTimeInMillis();
        //Third way using Iterator on keySet() in while loop
        Iterator<String> itr2 = testMap.keySet().iterator();
        while (itr2.hasNext()) {
            String key = itr2.next();
            testMap.get(key);
        }

        System.out.println("Using keySet() and iterator : " + (Calendar.getInstance().getTimeInMillis() - startTime));
    }

    public static void main(String[] args) {
        new ComparingMapLoop().testMapLoop();
    }
}

运行结果:

Using entrySet() in for-each loop : 62
Using keySet() in for-each loop : 89
Using entrySet() and iterator : 58
Using keySet() and iterator : 81


你可以立马就可以下一个结论,使用entry set 产生的性能相对于key set 迭代来说更强大。当然,其根本原因是使用迭代的方式不同, key set 会两次去执行Map检索查找对已的key-value键值对。



### 关于 `map` 遍历与浅拷贝、深拷贝的区别 在 JavaScript 中,`Array.prototype.map()` 方法用于创建一个新数组,该数组由调用回调函数的结果组成。它并不会直接修改原数组的内容,而是基于原数组的每一项生成新的值并存入新数组。 #### 1. **`map` 是否属于浅拷贝** 当使用 `map` 对数组进行操作时,如果数组中的元素是基本数据类型(如字符串、数字),那么生成的新数组将是独立的副本,这可以视为一种浅拷贝的行为[^3]。然而,如果是引用类型的对象或数组作为元素存在,则新数组中的这些元素仍然会保留原有的引用关系。这意味着对新数组中某个对象的操作可能会影响到原数组对应的对象实例。 #### 2. **浅拷贝 vs 深拷贝** - **浅拷贝**: 只复制一层结构的数据。对于简单数据类型来说,确实实现了真正的分离;但对于复杂数据类型比如嵌套的对象或者数组而言,仅仅是复制了顶层指针而已,内部深层级上的变化仍会影响彼此之间的状态同步情况[^2]。 - **深拷贝**: 不仅要复制最外层容器本身,还需要递归地处理其中包含的所有子节点直到整个树形结构都被完整重建为止。通过这种方式能够确保两个变量完全没有关联性即使它们最初来源于相同初始源材料[^4]。 #### 3. **行为特性分析** 考虑下面这个例子来具体说明三者的差异: ```javascript const original = [{ id: 1 }, { id: 2 }]; // 使用 map 进行变换 const mapped = original.map(item => ({ ...item })); original[0].id = 99; console.log(mapped); ``` 在这个场景下,虽然我们改变了原始数组第一个元素的 `id` 值为 `99` ,但由于我们在映射过程中利用解构语法 `{...item}` 制造出了全新的对象实体而非单纯传递原有项目链接过去,最终打印出来的结果表明 `mapped` 数组保持不变依旧显示 `[{"id":1},{"id":2}]` 。这种做法实际上构成了某种程度意义上的“深拷贝”,因为它切断了部分潜在联系但是需要注意的是这只是表面现象因为其他更深层次字段如果没有特别对待的话还是有可能继续维持原来那种互相干扰的状态除非采取更加彻底措施像自定义编写专门用来执行全面深入克隆工作的辅助工具函数那样才行[^5]。 ### 结论总结 综上所述,在大多数情况下,默认情况下 `map` 的运用倾向于形成所谓的浅层次仿制效果——即仅仅针对单维度层面做文章而不涉及更多细节方面考量;不过借助某些特定技巧例如扩展运算符之类的手段也可以达成接近甚至达到真正意义上全方位无死角版本也就是所谓严格意义下的深度复制目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值