HashMap vs TreeMap vs Hashtable vs LinkedHashMap
Map是一個重要的數(shù)據(jù)結(jié)構(gòu),本篇文章將介紹如何使用不同的Map,如HashMap,TreeMap,HashTable和LinkedHashMap。
Map概覽
Java中有四種常見的Map實現(xiàn),HashMap,TreeMap,HashTable和LinkedHashMap,我們可以使用一句話來描述各個Map,如下:
HashMap:基于散列表實現(xiàn),是無序的;TreeMap:基于紅黑樹實現(xiàn),按Key排序;LinkedHashMap:保存了插入順序;Hashtable:是同步的,與HashMap類似;HashMap
如果HashMap的Key是自己定義的對象,那么一般需要覆蓋equals()和hashCode()方法,且要遵循他們之間的約定。
package simplejava; import java.util.HashMap; import java.util.Map.Entry; class Dog { String color; Dog(String c) { color = c; } public String toString() { return color + " dog"; } } public class Q26 { 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()); } } }
結(jié)果輸出:
4
white dog - 5
red dog - 10
white dog - 20
black dog - 15
注意,我們不小心添加了兩個"white dogs“,但是HashMap仍然存儲它。這是不合理的,現(xiàn)在我們困惑到底有多少條白狗存入了HashMap,5還是20呢。
其實,Dog類應(yīng)該是這樣定義的:
class Dog { String color; Dog(String c) { color = c; } public boolean equals(Object o) { return ((Dog) o).color.equals(this.color); } public int hashCode() { return color.length(); } public String toString() { return color + " dog"; } }
結(jié)果輸出:
3
red dog - 10
white dog - 20
black dog - 15
原因是因為HashMap不允許兩個相同的元素存入,默認(rèn)情況下,Object的hashCode()和equals()會被用于判斷兩個對象是否相同。默認(rèn)的hashCode()方法對于不同的對象會返回不同的值,而equals()方法只有當(dāng)兩個引用相等,即指向同一個對象的時候才返回true。如果你不是很清楚,可以自己檢驗下hashCode()和equals()之間的關(guān)系。
舉個例子,可以檢驗下HashMap中最常用的方法,如iteration,print等。
TreeMap
TreeMap是按key排序的,讓我們先看下如下代碼,了解其“按key排序”思想。
package simplejava; import java.util.Map.Entry; import java.util.TreeMap; class Dog { String color; Dog(String c) { color = c; } public boolean equals(Object o) { return ((Dog) o).color.equals(this.color); } public int hashCode() { return color.length(); } public String toString() { return color + " dog"; } } public class Q26 { 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()); } } }
結(jié)果輸出:
Exception in thread "main" java.lang.ClassCastException: simplejava.Dog cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1188)
at java.util.TreeMap.put(TreeMap.java:531)
at simplejava.Q26.main(Q26.java:34)
由于TreeSet是基于Key排序的,所以作為key的對象需要相互比較,這就是為什么key需要實現(xiàn)Comparable接口。舉個例子,你可以使用字符串作為Key,因為String已經(jīng)實現(xiàn)了Comparable接口。
現(xiàn)在,讓我們改變一下Dog,讓它可比較,如下:
package simplejava; import java.util.Map.Entry; import java.util.TreeMap; 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 Q26 { 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()); } } }
結(jié)果打印:
red dog - 10
black dog - 15
white dog - 20
在這個例子中,我們是按dog的size來排序的;
如果"Dog d4 = new Dog("white", 10);"被替換成"Dog d4 = new Dog("white",40);",結(jié)果將輸出如下信息:
white dog - 20
red dog - 10
black dog - 15
white dog - 5
這是因為當(dāng)前TreeMap使用compareTo()去比較key,不同的size意味著不同的dogs。
HashTable
參考java文檔:HashMap與HashTable基本類似,除了非同步和允許null外。
LinkedHashMap
LinkedHashMap是HashMap的子類,意味著它繼承了HashMap的特性,除此之外,LinkedHashMap還保存了插入順序。
讓我們使用同樣的代碼,然后將HashMap替換成LinkedHashMap,如下:
package simplejava; import java.util.LinkedHashMap; import java.util.Map.Entry; class Dog { String color; Dog(String c) { color = c; } public boolean equals(Object o) { return ((Dog) o).color.equals(this.color); } public int hashCode() { return color.length(); } public String toString() { return color + " dog"; } } public class Q26 { 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()); } } }
輸出結(jié)果:
red dog - 10
black dog - 15
white dog - 20
如果我們使用HashMap,結(jié)果如下,區(qū)別在于沒有保存插入順序:
red dog - 10
white dog - 20
black dog - 15
更多閱讀:ArrayList vs. LinkedList vs. Vector
譯文鏈接:http://www.programcreek.com/2013/03/hashmap-vs-treemap-vs-hashtable-vs-linkedhashmap/
總結(jié)
以上所述是小編給大家介紹的HashMap vs TreeMap vs Hashtable vs LinkedHashMap的相關(guān)知識,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復(fù)大家的!
相關(guān)文章
Java Math.round(),Math.ceil(),Math.floor()的區(qū)別詳解
這篇文章主要介紹了Java Math.round(),Math.ceil(),Math.floor()的區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08Java 實戰(zhàn)練手項目之校園超市管理系統(tǒng)的實現(xiàn)流程
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+Mysql+Maven+Bootstrap實現(xiàn)一個校園超市管理系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2021-11-11使用java web 在jsp文件及Class中連接MySQL和SQLserver 的驅(qū)動方法
這篇文章主要介紹了使用java web 在jsp文件及Class中連接MySQL和SQLserver的驅(qū)動方法的相關(guān)資料,本文介紹的非常詳細(xì),具有參考借鑒價值,需要的朋友可以參考下2016-10-10MyBatis實現(xiàn)動態(tài)SQL的實現(xiàn)方法
這篇文章主要介紹了MyBatis實現(xiàn)動態(tài)SQL的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12基于Java字符串 "==" 與 "equals" 的深入理解
本篇文章是對Java中的字符串"=="與"equals"進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06解決idea 拉取代碼出現(xiàn)的 “ Сannot Run Git Cannot identify version of
這篇文章主要介紹了解決idea 拉取代碼出現(xiàn)的 “ Сannot Run Git Cannot identify version of git executable: no response“的問題,需要的朋友可以參考下2020-08-08如何開發(fā)一個簡單的Akka Java應(yīng)用
這篇文章主要介紹了如何開發(fā)一個簡單的Akka Java應(yīng)用 ,幫助大家使用Java創(chuàng)建Akka項目并將其打包,感興趣的朋友可以了解下2020-10-10spring實現(xiàn)bean對象創(chuàng)建代碼詳解
這篇文章主要介紹了spring實現(xiàn)bean對象創(chuàng)建代碼詳解,具有一定借鑒價值,需要的朋友可以參考下2017-12-12Spring獲取當(dāng)前類在容器中的beanname實現(xiàn)思路
這篇文章主要介紹了Spring獲取當(dāng)前類在容器中的beanname,實現(xiàn)思路只需繼承BeanNameAware接口,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07