Map 0f Java

整理关于Java的Map相关的知识,最近面试有被问到关于此类数据结构的知识,故写下来总结一番。

List和Map都是java.util里面有关集合的数据结构类。Map主要的功能是元素对(键值对)的形式,每个键都映射到一个类。接下来我们介绍Map的分类、初始化、遍历的方式、排序方法以及常用API。

Map类

Java中的Map类可分为三种:

  • 通用Map:用于在应用程序内管理映射,通常在java.utils内
    • HashMap、
    • Hashtable、
    • Properties、
    • LinkedHashMap、
    • IdentityHashMap、
    • TreeMap、WeakHashMap、
    • ConcurrentHashMap
  • 专用Map:不必我们自己创建,而是通过其他应用程序访问
    • java.util.jar.Attribute、javax.print.attribute.standard.PrinterStateReasons、java.security.Provider、java.awt.RenderingHints、javax.swing.UIDefaults
  • 自定义Map

常用类型的区别

  • HashMap
    • 最常用的Map,速度快,非同步(不支持线程同步)
    • 允许一条键为null:多了覆盖
    • 允许多条值为null
  • TreeMap
    • 用Iterator遍历的时候返回以key为序的序列
    • 故不允许key为空
    • 非同步
  • HashTable
    • 类似HashMap,但是写入速度慢
    • 因为支持线程同步:同一时刻只能有一线程能写HashTable
  • LinkedHashMap
    • 保持了插入顺序,Iterator遍历时先进先出
    • key、value都允许为空

用法

1
2
3
4
5
6
7
8
9
10
11
//建立
HashMap<String, String> map = new HashMap<String, String>();
//寻值
map.get("key1");
//插入
map.put("key2", "value2");
//移除
map.remove("key1");
//清空
map.clear();
//

Map的遍历

初始化

1
2
3
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
map.put("key2", "value2");

分别使用增强for循环和Iterator来遍历

增强for循环遍历

KeySet遍历

1
2
3
for (String key: map.keySet()){
System.out.println(key + ": " + map.get(key));
}

entrySet遍历

1
2
for (Map.Entry<String, String> entry: map.entrySet()){
System.out.println(entry.getKey() + ": " + entry.getValue());

Iterator遍历

KeySet遍历

1
2
3
4
5
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()){
String key = iterator.next();
System.out.println(key + ": " + map.get(key));
}

entrySet遍历

1
2
3
4
5
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
System.out.println(entry.getKey() + ":" + entry.getValue());
}

遍历性能

就实验比较,

  • 增强for循环使用方便,但性能较差,不适合处理超大量级的数据。

  • 迭代器的遍历速度要比增强for循环快很多,是增强for循环的2倍左右。

  • 使用entrySet遍历的速度要比keySet快很多,是keySet的1.5倍左右。

排序

TreeMap排序,若是升序只需要按序输出即可,降序需要改写比较器:

1
2
3
4
5
6
7
8
9
10
11
12
Map<String, String> map = new TreeMap<String, String>(new Comparator<String>() {
public int compare(String obj1, String obj2) {
return obj2.compareTo(obj1);// 降序排序
}
});
map.put("a", "c");
map.put("b", "b");
map.put("c", "a");

for (String key : map.keySet()) {
System.out.println(key + " :" + map.get(key));
}

HashMap\HashTable\LinkedHashMap排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Map<String, String> map = new HashMap<String, String>();
map.put("a", "c");
map.put("b", "b");
map.put("c", "a");

// 通过ArrayList构造函数把map.entrySet()转换成list
List<Map.Entry<String, String>> list = new ArrayList<Map.Entry<String, String>>(map.entrySet());
// 通过比较器实现比较排序
Collections.sort(list, new Comparator<Map.Entry<String, String>>() {
public int compare(Map.Entry<String, String> mapping1, Map.Entry<String, String> mapping2) {
return mapping1.getKey().compareTo(mapping2.getKey());
}
});

for (Map.Entry<String, String> mapping : list) {
System.out.println(mapping.getKey() + " :" + mapping.getValue());
}

常用API

method 作用
clear() 从 Map 中删除所有映射
remove(Object key) 从 Map 中删除键和关联的值
put(Object key, Object value) 将指定值与指定键相关联
putAll(Map t) 将指定 Map 中的所有映射复制到此 map
entrySet() 返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素
keySet() 返回 Map 中所包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值)
values() 返回 map 中所包含值的 Collection 视图。删除 Collection 中的元素还将删除 Map 中相应的映射(键和值)
get(Object key) 返回与指定键关联的值
containsKey(Object key) 如果 Map 包含指定键的映射,则返回 true
containsValue(Object value) 如果此 Map 将一个或多个键映射到指定值,则返回 true
isEmpty() 如果 Map 不包含键-值映射,则返回 true
size() 返回 Map 中的键-值映射的数目