Map接口有以下几个常见的实现类:
HashMap
元素为键值对,键具有唯一性。
- JDK 1.8中基于位桶 + 链表 + 红黑树实现
- 线程不安全
- 键无序
构造方法
默认构造方法:
1
HashMap<Key, Value> map = new HashMap<>();
也可以在构造时指定 容量(Capacity) 和 负载因子(loadFactor),例:
1
HashMap<Key, Value> map = new HashMap<>(8, 0.5f);
常用方法
方法 | 描述 |
---|---|
put(K, V) | 将键值对添加至map中,若键已存在则更新值 |
get(K) | 返回指定键对应的值,若键不存在则返回null |
getOrDefault(K, defaultValue) | 返回指定键对应的值,若键不存在则返回指定的defaultValue |
containsKey(K) | 判断指定的键是否在map中 |
remove(K) | 删除指定键及其对应的值,并返回该值,若键不存在则返回null |
keySet() | 返回map中所有键的集合 |
values() | 返回map中所有值的集合 |
entrySet() | 返回map中所有映射关系的集合 |
代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.util.*;
public class hashmap{
public static void main(String[] args){
/* initialization */
Character[] letters = {'a', 'b', 'c', 'd', 'e'};
Integer[] nums = {1, 2, 3, 4, 5};
HashMap<Character, Integer> alpha2num = new HashMap<>();
for (int i = 0; i < letters.length; i++){
alpha2num.put(letters[i], nums[i]);
}
print("map:", alpha2num);
/* get */
print("get c:", alpha2num.get('c'));
print("get r:", alpha2num.get('r'));
/* getOrDefault */
print("get or default c:", alpha2num.getOrDefault('c', 10));
print("get or default r:", alpha2num.getOrDefault('r', 10));
/* containsKey */
print("contains b:", alpha2num.containsKey('b'));
/* remove */
print("remove d:", alpha2num.remove('d'));
print("remove r:", alpha2num.remove('r'));
print("current map:", alpha2num);
/* keySet */
print("key set:", alpha2num.keySet());
/* values */
print("values:", alpha2num.values());
/* entrySet */
printEntry("k-v pairs:", alpha2num.entrySet());
}
public static void print(String prompt, HashMap<Character, Integer> map){
System.out.println(String.format("%-20s %-20s", prompt, map));
}
public static void print(String prompt, Integer num){
System.out.println(String.format("%-20s %-20s", prompt, num));
}
public static void print(String prompt, boolean flag){
System.out.println(String.format("%-20s %-20s", prompt, flag));
}
public static void print(String prompt, Set<Character> keys){
System.out.println(String.format("%-20s %-20s", prompt, keys));
}
public static void print(String prompt, Collection<Integer> values){
System.out.println(String.format("%-20s %-20s", prompt, values));
}
public static void printEntry(String prompt, Set<Map.Entry<Character, Integer>> entry){
System.out.println(String.format("%-20s %-20s", prompt, entry));
}
}
输出:
1
2
3
4
5
6
7
8
9
10
11
12
map: {a=1, b=2, c=3, d=4, e=5}
get c: 3
get r: null
get or default c: 3
get or default r: 10
contains b: true
remove d: 4
remove r: null
current map: {a=1, b=2, c=3, e=5}
key set: [a, b, c, e]
values: [1, 2, 3, 5]
k-v pairs: [a=1, b=2, c=3, e=5]
遍历方式
可以遍历map中的键、值与键值对,遍历时使用forEach:
1
2
3
for (Character key: alpha2num.keySet()) System.out.print(key + " ");
for (Integer value: alpha2num.values()) System.out.print(value + " ");
for (Map.Entry<Character, Integer> entry: alpha2num.entrySet()) System.out.print("(" + entry + " " + entry.getKey() + " " + entry.getValue() + ") ");
输出:
1
2
3
a b c e
1 2 3 5
(a=1 a 1) (b=2 b 2) (c=3 c 3) (e=5 e 5)
LinkedHashMap
LinkedHashMap是HashMap的子类,其构造与常用方法与HashMap一致。在LinkedHashMap内部维护着一个双向链表,这使得其中的键有序。关于键的无序与有序性,验证如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.*;
public class linkedhashmap {
public static void main(String[] args){
HashMap<Integer, Integer> map1 = new HashMap<>();
LinkedHashMap<Integer, Integer> map2 = new LinkedHashMap<>();
Integer[] nums = {3, 4, 1, 2};
for (Integer num: nums){
map1.put(num, null);
map2.put(num, null);
}
System.out.print(String.format("%-25s", "HashMap keys:"));
for (Integer key: map1.keySet()) System.out.print(key + " ");
System.out.println("");
System.out.print(String.format("%-25s", "LinkedHashMap keys:"));
for (Integer key: map2.keySet()) System.out.print(key + " ");
}
}
输出:
1
2
HashMap keys: 1 2 3 4
LinkedHashMap keys: 3 4 1 2
TreeMap
是Map的子接口SortedMap的实现类,其内部的键会被排序。默认为升序排序,也可以使用Comparator自定义排序方式。
构造方法
1
TreeMap<K, V> map = new TreeMap<>();
常用方法
关于操作与访问TreeMap的方法与HashMap中提到的一致。除此之外,它还提供了各种导航方法,效果与TreeSet中类似的方法一致:
方法 | 描述 |
---|---|
firstKey() lastKey() | 返回第一个键 返回最后一个键 |
higherKey(K) ceilingKey(K) | 返回map中大于指定键的最小键 返回map中大于等于指定键的最小键 |
lowerKey(K) floorKey(K) | 返回map中小于指定键的最大键 返回map中小于等于指定键的最大键 |
pollFirstEntry() pollLastEntry() | 返回并删除第一个键值对 返回并删除最后一个键值对 |
headMap(K, boolean b) | 返回指定键之前的所有键值对,b 默认为false ,不包含边界 |
tailMap(K, boolean b) | 返回指定键之后的所有键值对,b 默认为true ,包含边界 |
subMap(K1, boolean b1, K2, boolean b2) | 返回指定键之间的所有键值对,b1 默认为true ,b2 默认为false ,左闭右开 |
代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import java.util.*;
public class treemap {
public static void main(String[] args){
/* initialization */
Character[] letters = {'a', 'd', 'e', 'c', 'b', 'g', 'f'};
Integer[] nums = {3, 4, 2, 1, 5, 7, 6};
TreeMap<Character, Integer> map1 = new TreeMap<>();
for (int i = 0; i < letters.length; i++) map1.put(letters[i], nums[i]);
print("treemap:", map1);
TreeMap<Character, Integer> map2 = new TreeMap<>(Comparator.comparing(map1::get));
map2.putAll(map1);
print("sort by value:", map2);
/* firstKey & lastKey */
print("map1 first:", map1.firstKey());
print("map1 last:", map1.lastKey());
/* higherKey & ceilingKey */
print("higher key c:", map1.higherKey('c'));
print("ceiling key c:", map1.ceilingKey('c'));
/* lowerKey & floorKey() */
print("lower key b:", map1.lowerKey('b'));
print("flooring key b:", map1.floorKey('b'));
/* poll */
print("poll first:", map1.pollFirstEntry());
print("poll last", map1.pollLastEntry());
print("current treemap:", map1);
/* headMap */
print("head c:", map1.headMap('c', true));
/* tailMap */
print("tail c:", map1.tailMap('c', false));
/* subMap */
print("sub b to e:", map1.subMap('b', false, 'e', true));
}
public static void print(String prompt, TreeMap<Character, Integer> map){
System.out.println(String.format("%-25s %-25s", prompt, map));
}
public static void print(String prompt, Character key){
System.out.println(String.format("%-25s %-25s", prompt, key));
}
public static void print(String prompt, Map.Entry<Character, Integer> entry){
System.out.println(String.format("%-25s %-25s", prompt, entry));
}
public static void print(String prompt, NavigableMap<Character, Integer> map){
System.out.println(String.format("%-25s %-25s", prompt, map));
}
}
输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
treemap: {a=3, b=5, c=1, d=4, e=2, f=6, g=7}
sort by value: {c=1, e=2, a=3, d=4, b=5, f=6, g=7}
map1 first: a
map1 last: g
higher key c: d
ceiling key c: c
lower key b: a
flooring key b: b
poll first: a=3
poll last g=7
current treemap: {b=5, c=1, d=4, e=2, f=6}
head c: {b=5, c=1}
tail c: {d=4, e=2, f=6}
sub b to e: {c=1, d=4, e=2}
HashTable
- 旧版本的遗留类
- 不允许键或值为null
- 线程安全,但多线程场景现如今多用ConcurrentHashMap
- 不推荐使用