一、什么是 Map
不同于 List 单列的线性结构,Java 中的 Map 提供的是一种双列映射的存储集合,它能够提供一对一的数据处理能力,双列中的第一列我们称为 key,第二列就是 value,一个 key 只能够在一个 Map 中出现最多一次,通过一个 key 能够获取 Map 中唯一一个与之对应的 value 值,正是它的这种一对一映射的数据处理关系,在实际应用中可以通过一个 key 快速定位到对应的 value。
Map 的三个特点:
包含键值对
键唯一
键对应的值唯一
二、Map 集合常用的遍历方式
遍历 Map 集合的常用方式有三种:
使用 keySet 的方式
使用 entrySet 的方式
使用 values() 取值的方式
这三种方式中,都有对应的 for 循环遍历和 Iterator 遍历的方式取值。
keySet 是键的集合,Set 里面的类型即 key 的类型;
entrySet 是键 - 值对的集合,Set 里面的类型是 Map.Entry,Entry 是一个键 - 值对;
keySet():迭代后只能通过 get() 取 key;
entrySet():迭代后可以 e.getKey(),e.getValue() 取 key 和 value,返回的是 Entry 接口;
三、遍历的性能对比
for each 与显示调用 Iterator 等价,除了第三种方式 (for each map.keySet()),再调用 get 获取方式外,其他三种方式性能相当。本例还是 hash 值散列较好的情况,若散列算法较差,第三种方式会更加耗时。
1、在数据元素的数量比较大时,entrySet() 方式的遍历效率快于 keySet(),有两个原因:
(1)一个原因是 keySet 相当于遍历了 2 次,一次是对 key 的 Set 集合的遍历,二次是每次遍历过程都要通过 key 和 map.get(key) 来获取 value 值。
(2)第二个原因是 map.get(key) 的时候,底层是根据 key 的 hashCode 值经过哈希算法得到一个 hash 值,然后作为索引映射到对应的 table 数组的索引位置,这是一次密集型计算,很耗费 CPU,如果有大量的元素,则会使 CPU 使用率飙升,影响响应速度,而 entrySet() 返回的 set 里面的元素都是 Map.Enpty 类型,key 和 value 就是这个类的一个属性,entry.getKey() 和 entry.getValue() 效率肯定很高。
2、不过,在数据元素的数量比较小的情况小,keySet() 方式的遍历效率快于 entrySet()。
3、values() 是返回 Map 的所有 value 的集合的 Collection,只能遍历到 value,很难遍历到 key,所以一般不用,如果当我们只需要取得 value 值时,采用 values 来遍历效率更高。
4、从上面的几种方式的 for 循环遍历和 Iterator 遍历的方式耗时结果来看,Iterator 遍历的效率会比 for 循环效率更快一点。