Java SE中有四種常見的Map實現——HashMap, TreeMap, Hashtable和LinkedHashMap。若是咱們使用一句話來分別歸納它們的特色,就是:java
HashMap就是一張hash表,鍵和值都沒有排序。安全
TreeMap以紅-黑樹結構爲基礎,鍵值按順序排列。oop
LinkedHashMap保存了插入時的順序。this
Hashtable是同步的(而HashMap是不一樣步的)。因此若是在線程安全的環境下應該多使用HashMap,而不是Hashtable,由於Hashtable對同步有額外的開銷。spa
HashMap線程
若是HashMap的鍵(key)是自定義的對象,那麼須要按規則定義它的equals()和hashCode()方法。code
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()); } } }
輸出:htm
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類應該定義以下:排序
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的鍵按順序排列。讓咱們先看個例子看看什麼叫做「鍵按順序排列」。
package javaBasic; import java.util.TreeMap; import java.util.Map.Entry; 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 TreeMapTest { 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: javaBasic.Dog
at java.util.TreeMap.compare(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at javaBasic.TreeMapTest.main(TreeMapTest.java:35)
由於TreeMap按照鍵的順序進行排列對象,因此鍵的對象之間須要可以比較,因此就要實現Comparable接口。你可使用String做爲鍵,String已經實現了Comparable接口。
咱們來修改下Dog類,讓它實現Comparable接口。
package javaBasic; import java.util.TreeMap; import java.util.Map.Entry; class Dog implements Comparable<Dog>{ String color; int size; Dog(String c, int s) { color = c; size = s; } public String toString(){ return color + " dog"; } public int compareTo(Dog o) { return o.size - this.size; } } public class TreeMapTest { 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()); } } }
輸出:
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);」,那麼輸出會變成:
white dog - 20
red dog - 10
black dog - 15
white dog - 5
這是由於TreeMap使用compareTo()方法來比較鍵值的大小,size不相等的狗是不一樣的狗。
Java文檔寫道:
HashMap類和Hashtable類幾乎相同,不一樣之處在於HashMap是不一樣步的,也容許接受null鍵和null值。
LinkedHashMap是HashMap的子類,因此LinkedHashMap繼承了HashMap的一些屬性,它在HashMap基礎上增長的特性就是保存了插入對象的順序。
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()); } } }
red dog - 10
black dog - 15
white dog - 20
若是咱們使用HashMap的話,輸出將會以下,會打亂插入的順序:.
package javaBasic; import java.util.HashMap; import java.util.Map.Entry; /** * HashMap就是一張hash表,鍵和值都沒有排序。 * @author markGao * */ public class HashMapTest { 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 //若是咱們使用HashMap的話,輸出將會以下,會打亂插入的順序: for (Entry<Dog, Integer> entry : hashMap.entrySet()) { System.out.println(entry.getKey().toString() + " - " + entry.getValue()); } } }
1
2
3
|
red dog - 10
white dog - 20
black dog - 15
|