Java为数据结构中的映射定义了一个接口java.util.Map,它有四个实现类,分别是HashMap、HashTable、LinkedHashMap和TreeMap。本节实例主要介绍这4中实例的用法和区别。
关键技术剖析:
Map用于存储键值对,根据键得到值,因此不允许键重复,值可以重复。
l (1)HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为null,不允许多条记录的值为null。HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要同步,可以用Collections.synchronizedMap(HashMap map)方法使HashMap具有同步的能力。
l (2)Hashtable与HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,然而,这也导致了Hashtable在写入时会比较慢。
l (3)LinkedHashMap保存了记录的插入顺序,在用Iteraor遍历LinkedHashMap时,先得到的记录肯定是先插入的。在遍历的时候会比HashMap慢。有HashMap的全部特性。
l (4)TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器。当用Iteraor遍历TreeMap时,得到的记录是排过序的。TreeMap的键和值都不能为空。
关键技术剖析:
Map用于存储键值对,根据键得到值,因此不允许键重复,值可以重复。
l (1)HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为null,不允许多条记录的值为null。HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要同步,可以用Collections.synchronizedMap(HashMap map)方法使HashMap具有同步的能力。
l (2)Hashtable与HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,然而,这也导致了Hashtable在写入时会比较慢。
l (3)LinkedHashMap保存了记录的插入顺序,在用Iteraor遍历LinkedHashMap时,先得到的记录肯定是先插入的。在遍历的时候会比HashMap慢。有HashMap的全部特性。
l (4)TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器。当用Iteraor遍历TreeMap时,得到的记录是排过序的。TreeMap的键和值都不能为空。
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
import
java.util.HashMap;
import
java.util.Hashtable;
import
java.util.Iterator;
import
java.util.LinkedHashMap;
import
java.util.Map;
import
java.util.TreeMap;
public
class
TestMap {
public
static
void
init(Map map){
if
(map !=
null
){
String key =
null
;
for
(
int
i=
5
; i>
0
; i--){
key =
new
Integer(i).toString() +
".0"
;
map.put(key, key.toString());
//Map中的键是不重复的,如果插入两个键值一样的记录,
//那么后插入的记录会覆盖先插入的记录
map.put(key, key.toString() +
"0"
); }
}
}
public
static
void
output(Map map){
if
(map !=
null
){
Object key =
null
;
Object value =
null
;
//使用迭代器遍历Map的键,根据键取值
Iterator it = map.keySet().iterator();
while
(it.hasNext()){
key = it.next();
value = map.get(key);
System.out.println(
"key: "
+ key +
"; value: "
+ value );
}
//或者使用迭代器遍历Map的记录Map.Entry
Map.Entry entry =
null
;
it = map.entrySet().iterator();
while
(it.hasNext()){
//一个Map.Entry代表一条记录
entry = (Map.Entry)it.next();
//通过entry可以获得记录的键和值
//System.out.println("key: " + entry.getKey() + "; value: " + entry.getValue());
}
}
}
public
static
boolean
containsKey(Map map, Object key){
if
(map !=
null
){
return
map.containsKey(key);
}
return
false
;
}
public
static
boolean
containsValue(Map map, Object value){
if
(map !=
null
){
return
map.containsValue(value);
}
return
false
;
}
public
static
void
testHashMap(){
Map myMap =
new
HashMap();
init(myMap);
//HashMap的键可以为null
myMap.put(
null
,
"ddd"
);
//HashMap的值可以为null
myMap.put(
"aaa"
,
null
);
output(myMap);
}
public
static
void
testHashtable(){
Map myMap =
new
Hashtable();
init(myMap);
//Hashtable的键不能为null
//myMap.put(null,"ddd");
//Hashtable的值不能为null
//myMap.put("aaa", null);
output(myMap);
}
public
static
void
testLinkedHashMap(){
Map myMap =
new
LinkedHashMap();
init(myMap);
//LinkedHashMap的键可以为null
myMap.put(
null
,
"ddd"
);
myMap.put(
null
,
"aaa"
);
//LinkedHashMap的值可以为null
myMap.put(
"aaa"
,
null
);
output(myMap);
}
public
static
void
testTreeMap(){
Map myMap =
new
TreeMap();
init(myMap);
//TreeMap的键不能为null
//myMap.put(null,"ddd");
//TreeMap的值不能为null
//myMap.put("aaa", null);
output(myMap);
}
public
static
void
main(String[] args) {
System.out.println(
"采用HashMap"
);
TestMap.testHashMap();
System.out.println(
"采用Hashtable"
);
TestMap.testHashtable();
System.out.println(
"采用LinkedHashMap"
);
TestMap.testLinkedHashMap();
System.out.println(
"采用TreeMap"
);
TestMap.testTreeMap();
Map myMap =
new
HashMap();
TestMap.init(myMap);
System.out.println(
"新初始化一个Map: myMap"
);
TestMap.output(myMap);
//清空Map
myMap.clear();
System.out.println(
"将myMap clear后,myMap空了么? "
+ myMap.isEmpty());
TestMap.output(myMap);
myMap.put(
"aaa"
,
"aaaa"
);
myMap.put(
"bbb"
,
"bbbb"
);
//判断Map是否包含某键或者某值
System.out.println(
"myMap包含键aaa? "
+ TestMap.containsKey(myMap,
"aaa"
));
System.out.println(
"myMap包含值aaaa? "
+ TestMap.containsValue(myMap,
"aaaa"
));
//根据键删除Map中的记录
myMap.remove(
"aaa"
);
System.out.println(
"删除键aaa后,myMap包含键aaa? "
+ TestMap.containsKey(myMap,
"aaa"
));
//获取Map的记录数
System.out.println(
"myMap包含的记录数: "
+ myMap.size());
}
}
输出结果:
采用HashMap
key:
null
; value: ddd
key:
3.0
; value:
3.00
key: aaa; value:
null
key:
4.0
; value:
4.00
key:
1.0
; value:
1.00
key:
5.0
; value:
5.00
key:
2.0
; value:
2.00
采用Hashtable
key:
4.0
; value:
4.00
key:
1.0
; value:
1.00
key:
3.0
; value:
3.00
key:
5.0
; value:
5.00
key:
2.0
; value:
2.00
采用LinkedHashMap
key:
5.0
; value:
5.00
key:
4.0
; value:
4.00
key:
3.0
; value:
3.00
key:
2.0
; value:
2.00
key:
1.0
; value:
1.00
key:
null
; value: aaa
key: aaa; value:
null
采用TreeMap
key:
1.0
; value:
1.00
key:
2.0
; value:
2.00
key:
3.0
; value:
3.00
key:
4.0
; value:
4.00
key:
5.0
; value:
5.00
新初始化一个Map: myMap
key:
3.0
; value:
3.00
key:
4.0
; value:
4.00
key:
1.0
; value:
1.00
key:
5.0
; value:
5.00
key:
2.0
; value:
2.00
将myMap clear后,myMap空了么?
true
myMap包含键aaa?
true
myMap包含值aaaa?
true
删除键aaa后,myMap包含键aaa?
false
myMap包含的记录数:
1
源码分析:
遍历Map有两种方法:
(
1
)map的keySet()方法获得键的集合,再调用键集合的iterator方法获得键的迭代器,以此迭代地取出Map中的键,用get方法获得键对应的值,便完成了Map的遍历。代码如下所示:
//使用迭代器遍历Map的键,根据键取值
Iterator it = map.keySet().iterator();
while
(it.hasNext()){
key = it.next();
value = map.get(key);
System.out.println(
"key: "
+ key +
"; value: "
+ value );
}
(
2
)使用Map的entrySet方法获得Map中记录的集合,每条对象都是一个Map.Entry对象,使用其getKey方法获得记录的键,使用其getValue方法获得记录的值。代码如下所示:
//或者使用迭代器遍历Map的记录Map.Entry
Map.Entry entry =
null
;
it = map.entrySet().iterator();
while
(it.hasNext()){
//一个Map.Entry代表一条记录
entry = (Map.Entry)it.next();
//通过entry可以获得记录的键和值
//System.out.println("key: " + entry.getKey() + "; value: " + entry.getValu
|