天天看點

HashMap、TreeMap、Hashtable、LinkedHashMap四者比較1. Map概覽2. HashMap3. TreeMap4. Hashtable5. LinkedHashMap

    Map是一種很重要的資料結構。在本文中,我會告訴你們如何使用HashMap、TreeMap、Hashtable、LinkedHashMap這四種map。

1. Map概覽

HashMap、TreeMap、Hashtable、LinkedHashMap四者比較1. Map概覽2. HashMap3. TreeMap4. Hashtable5. LinkedHashMap

    在Java SE中,Map有四種常用的實作:HashMap、TreeMap、Hashtable和LinkedHashMap。我們可以使用一句話來分别描述各種實作,如下:

    ① HashMap是作為哈希表(hash table)實作的,其中的鍵(key)和值(value)沒有順序。

    ② TreeMap是基于紅黑樹(red-black tree)結構實作的,其中的元素根據鍵(key)進行排序。

    ③ LinkedHashMap保留了元素的插入順序。

    ④ Hashtable是同步的,這一點和HashMap不同。

    是以,線上程安全(thread-safe)的情況下,應使用HashMap,因為Hashtable需要額外的同步開銷。

2. HashMap

    如果HashMap中的鍵(key)是自定義的對象,那麼該對象需要遵循equals()和hashCode()協定。

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<Dog, Integer> hashMap = new HashMap<Dog, Integer>();
        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<Dog, Integer> entry : hashMap.entrySet()) {
            System.out.println(entry.getKey().toString() + " - " + entry.getValue());
        }
    }
}
           

    輸出結果:

4
white dog – 5
black dog – 15
red dog – 10
white dog – 20
           

    這裡請注意,我們添加兩次”white dogs“,這本該是個錯誤,但HashMap卻照常執行。這就有點兒說不通了,我們現在不知道到底有多少”white dogs“。

    Dog類應該定義如下:

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";
    }
}
           

    現在輸出的結果是:

3
red dog – 10
white dog – 20
black dog – 15
           

    究其原因,HashMap中不允許存在兩個完全相同的元素。預設的,Object類中的hashCode()和equals()方法會被調用。預設的hashCode()方法為不同的對象配置設定不同的增速,而當兩個變量引用同一個對象時,equals()方法傳回true。如果你對此了解的不是特别清楚,請檢視文章 《the hashCode() and equals() contract》。

    檢視文章《the most frequently used methods for HashMap》,如iteration、print等等。

3. TreeMap

    TreeMap按鍵(key)對元素進行排序。為了了解“按key排序”的概念,我們首先看一下下面的例子:

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<Dog, Integer> treeMap = new TreeMap<Dog, Integer>();
        treeMap.put(d1, 10);
        treeMap.put(d2, 15);
        treeMap.put(d3, 5);
        treeMap.put(d4, 20);
 
        for (Entry<Dog, Integer> entry : treeMap.entrySet()) {
            System.out.println(entry.getKey() + " - " + entry.getValue());
        }
    }
}
           

    輸出結果:

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是按照鍵(key)進行排序的,用來當做鍵的對象互相之間必須能夠進行大小比較,是以它必須實作Comparable接口。例如,你可以将String作為鍵,因為String實作了Comparable接口。

    我們來修改一下Dog類,使它可以進行大小比較。

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<Dog, Integer> treeMap = new TreeMap<Dog, Integer>();
        treeMap.put(d1, 10);
        treeMap.put(d2, 15);
        treeMap.put(d3, 5);
        treeMap.put(d4, 20);
 
        for (Entry<Dog, Integer> entry : treeMap.entrySet()) {
            System.out.println(entry.getKey() + " - " + entry.getValue());
        }
    }
}
           

    輸出結果:

red dog – 10
black dog – 15
white dog – 20
           

    在本例中,TreeMap是按照鍵dog size進行排序的。

    如果“Dog d4 = new Dog("white", 10);”被替換為“Dog d4 = new Dog("white", 40);”,那麼輸出的結果會變成:

white dog – 20
red dog – 10
black dog – 15
white dog – 5
           

    因為TreeMap使用compareTo()方法來比較鍵,是以不同size的dog被認為是不相同的。

4. Hashtable

    來自Java文檔:HashMap類與Hashtable基本相同,但HashMap不是同步的,而且允許空值作為key或value。

5. LinkedHashMap

    LinkedHashMap是HashMap的子類,這意味着它繼承了HashMap的特性。而且,LinkedHashMap中的連結清單確定了元素的插入有序。

    我們将上面HashMap的示例程式中的HashMap替換為LinkedHashMap。

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<Dog, Integer> linkedHashMap = new LinkedHashMap<Dog, Integer>();
        linkedHashMap.put(d1, 10);
        linkedHashMap.put(d2, 15);
        linkedHashMap.put(d3, 5);
        linkedHashMap.put(d4, 20);
 
        for (Entry<Dog, Integer> entry : linkedHashMap.entrySet()) {
            System.out.println(entry.getKey() + " - " + entry.getValue());
        }		
    }
}
           

    輸出結果:

red dog – 10
black dog – 15
white dog – 20
           

    如果我們使用HashMap的話,由于不能保留元素插入的順序,是以輸出的結果也不同,如下:

red dog – 10
white dog – 20
black dog – 15
           

原文位址:HashMap vs. TreeMap vs. HashTable vs. LinkedHashMap