Map是最重要的数据结构。这篇文章中,我会带大家看看HashMap, TreeMap, HashTable和LinkedHashMap的区别。 java
Java SE中有四种常见的Map实现——HashMap, TreeMap, Hashtable和LinkedHashMap。若是咱们使用一句话来分别归纳它们的特色,就是: git
若是HashMap的键(key)是自定义的对象,那么须要按规则定义它的equals()和hashCode()方法。 github
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
|
classDog {
String color;
Dog(String c) {
color = c;
}
publicString toString(){
returncolor +" dog";
}
}
publicclassTestHashMap {
publicstaticvoidmain(String[] args) {
HashMap hashMap =newHashMap();
Dog d1 =newDog("red");
Dog d2 =newDog("black");
Dog d3 =newDog("white");
Dog d4 =newDog("white");
hashMap.put(d1,10);
hashMap.put(d2,15);
hashMap.put(d3,5);
hashMap.put(d4,20);
//print size
System.out.println(hashMap.size());
//loop HashMap
for(Entry entry : hashMap.entrySet()) {
System.out.println(entry.getKey().toString() +" - "+ entry.getValue());
}
}
}
|
输出: 安全
1
2
3
4
5
|
4
white dog - 5
black dog - 15
red dog - 10
white dog - 20
|
注意,咱们错误的将”white dogs”添加了两次,可是HashMap却接受了两只”white dogs”。这不合理(由于HashMap的键不该该重复),咱们会搞不清楚真正有多少白色的狗存在。 数据结构
Dog类应该定义以下: ide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
classDog {
String color;
Dog(String c) {
color = c;
}
publicbooleanequals(Object o) {
return((Dog) o).color ==this.color;
}
publicinthashCode() {
returncolor.length();
}
publicString toString(){
returncolor +" dog";
}
}
|
如今输出结果以下: 函数
1
2
3
4
|
3
red dog - 10
white dog - 20
black dog - 15
|
输出结果如上是由于HashMap不容许有两个相等的元素存在。默认状况下(也就是类没有实现hashCode()和equals()方法时),会使用Object类中的这两个方法。Object类中的hashCode()对于不一样的对象会返回不一样的整数,而只有两个引用指向的一样的对象时equals()才会返回true。若是你不是很了解hashCode()和equals()的规则,能够看看这篇文章。 oop
来看看HashMap最经常使用的方法,如迭代、打印等。 this
TreeMap的键按顺序排列。让咱们先看个例子看看什么叫做“键按顺序排列”。 spa
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
|
classDog {
String color;
Dog(String c) {
color = c;
}
publicbooleanequals(Object o) {
return((Dog) o).color ==this.color;
}
publicinthashCode() {
returncolor.length();
}
publicString toString(){
returncolor +" dog";
}
}
publicclassTestTreeMap {
publicstaticvoidmain(String[] args) {
Dog d1 =newDog("red");
Dog d2 =newDog("black");
Dog d3 =newDog("white");
Dog d4 =newDog("white");
TreeMap treeMap =newTreeMap();
treeMap.put(d1,10);
treeMap.put(d2,15);
treeMap.put(d3,5);
treeMap.put(d4,20);
for(Entry entry : treeMap.entrySet()) {
System.out.println(entry.getKey() +" - "+ entry.getValue());
}
}
}
|
输出:
1
2
3
|
Exception in thread "main" java.lang.ClassCastException: collection.Dog cannot be cast to java.lang.Comparable
at java.util.TreeMap.put(Unknown Source)
at collection.TestHashMap.main(TestHashMap.java:35)
|
由于TreeMap按照键的顺序进行排列对象,因此键的对象之间须要可以比较,因此就要实现Comparable接口。你可使用String做为键,String已经实现了Comparable接口。
咱们来修改下Dog类,让它实现Comparable接口。
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
|
classDogimplementsComparable<Dog>{
String color;
intsize;
Dog(String c,ints) {
color = c;
size = s;
}
publicString toString(){
returncolor +" dog";
}
@Override
publicintcompareTo(Dog o) {
return o.size -this.size;
}
}
publicclassTestTreeMap {
publicstaticvoidmain(String[] args) {
Dog d1 =newDog("red",30);
Dog d2 =newDog("black",20);
Dog d3 =newDog("white",10);
Dog d4 =newDog("white",10);
TreeMap treeMap =newTreeMap();
treeMap.put(d1,10);
treeMap.put(d2,15);
treeMap.put(d3,5);
treeMap.put(d4,20);
for(Entry entry : treeMap.entrySet()) {
System.out.println(entry.getKey() +" - "+ entry.getValue());
}
}
}
|
输出:
1
2
3
|
red dog - 10
black dog - 15
white dog - 20
|
结果根据键的排列顺序进行输出,在咱们的例子中根据size排序的。
若是咱们将“Dog d4 = new Dog(“white”, 10);”替换成“Dog d4 = new Dog(“white”, 40);”,那么输出会变成:
1
2
3
4
|
white dog - 20
red dog - 10
black dog - 15
white dog - 5
|
这是由于TreeMap使用compareTo()方法来比较键值的大小,size不相等的狗是不一样的狗,若是颜色不一样可是size相同则也算相同,具体看Dog类的cmpareTo()函数的实现。
Java文档写道:
HashMap类和Hashtable类几乎相同,不一样之处在于HashMap是不一样步的,也容许接受null键和null值。
LinkedHashMap is a subclass of HashMap. That means it inherits the features of HashMap. In addition, the linked list preserves the insertion-order.
Let’s replace the HashMap with LinkedHashMap using the same code used for HashMap.
LinkedHashMap是HashMap的子类,因此LinkedHashMap继承了HashMap的一些属性,它在HashMap基础上增长的特性就是保存了插入对象的顺序。
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
|
classDog {
String color;
Dog(String c) {
color = c;
}
publicbooleanequals(Object o) {
return((Dog) o).color ==this.color;
}
publicinthashCode() {
returncolor.length();
}
publicString toString(){
returncolor +" dog";
}
}
publicclassTestHashMap {
publicstaticvoidmain(String[] args) {
Dog d1 =newDog("red");
Dog d2 =newDog("black");
Dog d3 =newDog("white");
Dog d4 =newDog("white");
LinkedHashMap linkedHashMap =newLinkedHashMap();
linkedHashMap.put(d1,10);
linkedHashMap.put(d2,15);
linkedHashMap.put(d3,5);
linkedHashMap.put(d4,20);
for(Entry entry : linkedHashMap.entrySet()) {
System.out.println(entry.getKey() +" - "+ entry.getValue());
}
}
}
|
输出:
1
2
3
|
red dog - 10
black dog - 15
white dog - 20
|
若是咱们使用HashMap的话,输出将会以下,会打乱插入的顺序:
1
2
3
|
red dog - 10
white dog - 20
black dog - 15
|