Java SE中有四种常见的Map实现——HashMap, TreeMap, Hashtable和LinkedHashMap。如果我们使用一句话来分别概括它们的特点,就是:
如果HashMap的键(key)是自定义的对象,那么需要按规则定义它的equals()和hashCode()方法。
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
|
class Dog { String color; Dog(String c) { color = c; } public String toString(){ return color + " dog" ; } } public class TestHashMap { public static void main(String[] args) { HashMap hashMap = new HashMap(); Dog d1 = new Dog( "red" ); Dog d2 = new Dog( "black" ); Dog d3 = new Dog( "white" ); Dog d4 = new Dog( "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类应该定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class Dog { String color; Dog(String c) { color = c; } public boolean equals(Object o) { return ((Dog) o).color == this .color; } public int hashCode() { return color.length(); } public String toString(){ return color + " 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()的规则,可以看看这篇文章。
来看看HashMap最常用的方法,如迭代、打印等。
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
|
class Dog { String color; Dog(String c) { color = c; } public boolean equals(Object o) { return ((Dog) o).color == this .color; } public int hashCode() { return color.length(); } public String toString(){ return color + " dog" ; } } public class TestTreeMap { public static void main(String[] args) { Dog d1 = new Dog( "red" ); Dog d2 = new Dog( "black" ); Dog d3 = new Dog( "white" ); Dog d4 = new Dog( "white" ); TreeMap treeMap = new TreeMap(); 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
|
class Dog implements Comparable<Dog>{ String color; int size; Dog(String c, int s) { color = c; size = s; } public String toString(){ return color + " dog" ; } @Override public int compareTo(Dog o) { return o.size - this .size; } } public class TestTreeMap { public static void main(String[] args) { Dog d1 = new Dog( "red" , 30 ); Dog d2 = new Dog( "black" , 20 ); Dog d3 = new Dog( "white" , 10 ); Dog d4 = new Dog( "white" , 10 ); TreeMap treeMap = new TreeMap(); 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不相等的狗是不同的狗。
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
|
class Dog { String color; Dog(String c) { color = c; } public boolean equals(Object o) { return ((Dog) o).color == this .color; } public int hashCode() { return color.length(); } public String toString(){ return color + " dog" ; } } public class TestHashMap { public static void main(String[] args) { Dog d1 = new Dog( "red" ); Dog d2 = new Dog( "black" ); Dog d3 = new Dog( "white" ); Dog d4 = new Dog( "white" ); LinkedHashMap linkedHashMap = new LinkedHashMap(); 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 |
原文地址:http://www.cnblogs.com/mrgong/p/3816767.html