HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap(轉載)

Map是最重要的數據結構。這篇文章中,我會帶你們看看HashMap, TreeMap, HashTable和LinkedHashMap的區別。

1. Map概覽

Java SE中有四種常見的Map實現——HashMap, TreeMap, Hashtable和LinkedHashMap。如果我們使用一句話來分別概括它們的特點,就是:

  • HashMap就是一張hash表,鍵和值都沒有排序。
  • TreeMap以紅-黑樹結構爲基礎,鍵值按順序排列。
  • LinkedHashMap保存了插入時的順序。
  • Hashtable是同步的(而HashMap是不同步的)。所以如果在線程安全的環境下應該多使用HashMap,而不是Hashtable,因爲Hashtable對同步有額外的開銷。
  1. HashMap

如果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最常用的方法,如迭代、打印等。

3. 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
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不相等的狗是不同的狗。

4. Hashtable

Java文檔寫道:

HashMap類和Hashtable類幾乎相同,不同之處在於HashMap是不同步的,也允許接受null鍵和null值。

5. LinkedHashMap

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
原文鏈接: Programcreek 翻譯: ImportNew.com 唐小娟
譯文鏈接: http://www.importnew.com/8658.html
轉載請保留原文出處、譯者和譯文鏈接。]

關於作者: 唐小娟

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章