一、Map 概述
Java 中的 Map 是一个接口,表达的是映射的意思,使用 Map 能够高性能解决查找问题。实现 Map 接口的类都封装了高性能查找算法,利用 Map 接口的实现类就可以提高查找性能。
1、Map 的使用
- 存储——将需要查询的数据,按照 key-value (键值对) 成对存储到 map 对象中(其中,key 是被检索的关键字,value 是被查找到的信息);
- 查找——根据 key 查找对应的 value。
2、Map 的特点
- key 不能重复!value 可以重复。添加数据时,如果 key 重复就会替换原有的 value;
- 由于 Map 是以键值对存储的,所以在查找时,根据 key 检索到 value 的速度非常快,而和存储容量无关。
二、Map 的实现类
1、HashMap
最常用的 Map,根据键的 hashcode 值来存储数据,根据键可以直接获得对应的值,因此具有很快的访问速度。(HashMap 是最快的查找算法)
- HashMap 遍历时获取数据的顺序是随机的;
- HashMap 最多只允许一条记录的键为null,允许多条记录的值为null;
- HashMap不支持线程同步,如果需要同步,可以使用 synchronzied 关键字使得HashMap 具有同步的能力或者使用 concurrentHashMap。
- 使用 HashMap 存储自定义对象时,要重写 hashCode() 方法和 equals() 方法,
2、HashTable:
与 HashMap 类似(相当于 Vector 与 ArrayList 的关系),不同的是,它不允许记录的键或值为空。HashTable 支持线程同步,即任意时刻只能有一个线程写 HashTable,因此也导致 HashTable 在写入时比较慢!
3、LinkedHashMap:
保持了记录的插入顺序,遍历时,先插入的先出来。
4、TreeMap
实现了 SortedMap 接口,对保存的记录按照 key 来排序,默认是升序,也可以指定排序的比较器(和 TreeSet 相似)。TreeMap 不允许 key 为 null。
5、WeakHashMap
弱键映射,允许释放映射所指向的对象,这是为解决某类特殊问题而设计的。如果映射之外没有引用指向某个“键”,则此“键”可以被垃圾收集器回收。
6、ConcurrentHashMap
一种线程安全的 Map,它不涉及同步加锁。
7、IdentityHashMap
使用 == 代替 equals() 对键进行比较的散列映射,专为解决特殊问题设计的。
8、SortedMap 接口
SortedMap 接口继承自 Map 接口,更进一步提供基于键的总体排序。该映射是根据其键 key 的自然顺序进行排序的(可以实现 Comparable 接口或者提供 Comparator 比较器来实现排序)。
三、Map 的常用方法
以球员号码为键,球员名字为值,对 Map 方法进行简单测试。
1、put()——添加
将数据成对的添加到 map 中,其中 key 为键,value 为值。
Map<Integer, String> map = new HashMap<>();
map.put(24, "kobe");
map.put(30, "curry");
map.put(24, "white");
System.out.println(map);
结果:
{24=white, 30=curry}
注:
1、key 不能重复;
2、如果两次 put 同一个 key 的话,第一个 put 是添加,第二个 put 会覆盖第一个键值对。
2、get()——查找
通过给定的 key 来查询对应的 value 值,并将 value 返回。
System.out.println(map.get(30)); // curry
Map 是允许 value 为 null 的,当检索到 value 为空时,就返回null。
3、containsKey()
检查 map 中是否包含指定的 key,如果包含则返回 true,不包含则返回 false。
System.out.println(map.containsKey(30));// true
4、remove()——移除
删除给定的 key 对应的 value,并返回 value。
System.out.println(map.remove(24));// white
System.out.println(map.remove(25));// null
注:
如果要删除的 key 不存在,不会报错,会返回 null。
5、clear()——清空集合
map.clear();
6、keySet()——返回键集
返回 Map 中键的集合,可以用来遍历 Map。
Map<Integer, String> map = new HashMap<>();
map.put(24, "kobe");
map.put(30, "curry");
map.put(3, "pual");
System.out.println(map.keySet());
结果:
[3, 24, 30]
7、entrySet()
Map 中使用 Entry 内部类来表示一个映射项,映射项包含 key 和 value (每一个键值对就是一个 Entry),Map.Entry 里面包含 getKey() 和 getValue() 方法,可以分别获取键和值。而 entrySet()返回 Map 中键值对的集合,结合 getKey() 和 getValue() 方法,用来遍历 Map。
System.out.println(map.entrySet());
结果:
[3=pual, 24=kobe, 30=curry]
四、Map 的遍历
Map<Integer, String> map = new HashMap<>();
map.put(24, "kobe");
map.put(30, "curry");
map.put(3, "pual");
1、方式一:使用 keySet()
for(Integer key : map.keySet()){
System.out.println(key + " = " + map.get(key));
}
结果:
3 = pual
24 = kobe
30 = curry
2、方式二:使用 entrySet()
for(Entry<Integer, String> entry : map.entrySet()){
System.out.println(entry.getKey() + " = " + entry.getValue());
}
结果:
3 = pual
24 = kobe
30 = curry
3、方式三:使用迭代器
Iterator<Entry<Integer, String>> it = map.entrySet().iterator();
while(it.hasNext()){
Entry<Integer, String> entry = it.next();
System.out.println(entry.getKey() + " = " + entry.getValue());
}
结果:
3 = pual
24 = kobe
30 = curry