面試圖靈機器人的過程中被問到HashMap, Hashtable 和 TreeMap的區別,居然被問住了,雖然工作四年了,在解決具體問題時貌似還沒遇到過翻不過去的坑。但是最近的面試也深刻的認識到基礎知識該忘的忘,該不知道的不知道,究其原因,都是之前懶得或不屑總結。
就這個問題本身,回來學習後回答如下:
從兩個方面分析
一,是否可以使用null,作為key或者value
HashMap,可以使用null值作為key或者value,當null作為key時,由於HashMap的key,不可重復,所以最多可以存入一個key為null的Entry。而當null作為value時,可以有多個value為null的Entry。
Hashtable,不可以將null值作為key或value,當向Hashtable中放入null值時,會報NullPointExecption。
以上兩種,在內部實現時,均依靠key值使用Hash原理進行元素存儲。他們均是Map接口的典型實現類。
TreeMap,是SortedMap接口的實現類,而SortedMap繼承自Map接口。TreeMap內部維護以Key為排序依據的紅黑樹數據結構,當null作為key時,會NullPointException,但是當null用作value時可以有多個value為null的Entry。
驗證代碼如下:
import java.util.HashMap;
import java.util.Hashtable;
import java.util.TreeMap;
public class MapNullTest {
public static void main(String[] args) {
//1. HashMap null test
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put(null, null);
hashMap.put(null, null);
hashMap.put("a", null);
hashMap.put("b", null);
System.out.println("hashMap: " + hashMap);
//2. HashTable null test
Hashtable<String, String> hashTable = new Hashtable();
try {
hashTable.put(null, "a");
} catch (NullPointerException e) {
System.out.println("hashTable put (null, a) NullPointerException");
}
try {
hashTable.put("a", null);
} catch (Exception e) {
System.out.println("hashTable put (a, null) NullPointerException");
}
System.out.println("hashTable: " + hashTable);
//3. TreeMap null test
TreeMap<String, String> treeMap = new TreeMap<>();
try {
treeMap.put(null, "a");
} catch (NullPointerException e) {
System.out.println("treeMap put (null, a) NullPointException");
}
treeMap.put("a", null);
treeMap.put("b", null);
System.out.println("treeMap: " + treeMap);
}
}
執行結果如下:
hashMap: {null=null, a=null, b=null}
hashTable put (null, a) NullPointerException
hashTable put (a, null) NullPointerException
hashTable: {}
treeMap put (null, a) NullPointException
treeMap: {a=null, b=null}
二、是否是線程安全的
HashMap 和 TreeMap均不是線程安全的,如需要線程安全時,可使用Collections的synchronizedXxx()方法獲取到對應的線程安全對象。
Hashtable 是線程安全的。
Java 集合總結
java 集合類主要由兩個接口派生而出,Collection 和 Map接口。
一、Collection 族
其子接口有,Set,Queue和List接口。
1、Set 無序集合,集合中元素不可重復,常用Set類。
HashSet 元素的排列無序,不是線程同步的,集合中的元素可以為null,但是只可以有一個,其中的元素,因為不可以重復,所以需要判斷兩個對象是否相等,判斷標准為兩個對象通過equals()判斷為true,且hashCode()方法返回值也相等。LinkedHashSet是其子類,它依然是一個HashSet,但內部使用鏈表記錄了元素的添加順序,所以其中元素的順序與添加順序是一致的。
TreeSet 內部使用紅黑樹來存儲集合元素,加入TreeSet中的元素需要實現Comparable接口,因為TreeSet需要調用compareTo方法對元素進行比較從而排序,所以TreeSet中的元素順序,不是插入順序,而是compareTo的比較順序。TreeSet判斷兩個對象是否相等的唯一標准就是compareTo返回值是否為0。若內部元素未實現Comparable接口,則需要在創建TreeSet對象時為其指名排序規則,以一個Comparator對象與集合關聯,以指名排序規則。
EnumSet 專門為Enum對象設計的Set。
2、List 代表一個有序可重復的集合,且每一個元素都有對應的索引。
ArrayList 典型的List 實現類。
3、Queue 模擬隊列的數據結構
PriorityQueue 標准的對列實現類,不過其隊列中元素的排序並非按照入隊順序排列,而是依照元素實現的Comparable接口或者與集合綁定的Comparator對象定義的標准進行排列的,在出隊時按照元素的排列順序進行出隊。
Deque 是Queue的子接口。
ArrayDeque是 Deque的典型實現類,實現雙向隊列,也可用作Stack來使用。
LinkedList 實現了List接口同時也實現了Deque接口,所以它是一個功能強大的結合,即可作為List使用,也可作為雙向隊列或棧來使用。
二、Map族
參照面試問題的回答,另外就是有幾個重要的實現類:
WeakHashMap,保留對Key所引用對象的弱引用,可在key所引用的對象沒有其它引用時,自動刪除該key-value,以保證該元素的釋放。
Properties,封裝了對屬性文件的讀寫,可以方便的將key-value的屬性文件讀入Properties對象中,也可方便的將Properties對象方便的存入屬性文件中。