HashMap與Hashtable的使用
1、繼承的父類不同 HashMap和Hashtable不僅作者不同,而且連父類也是不一樣的。HashMap是繼承自AbstractMap類,而HashTable是繼承自Dictionary類。不過它們都實現了同時實現了map、Cloneable(可複製)、Serializable(可序列化)這三個介面
HashMap與實體的使用
@RequestMapping("/getHisByUserId/{userId}") public AssembleJSON getChromaHis(@PathVariable Integer userId){ return AssembleJSON.SUCCESS(service.getDataHisByUserId(userId)); }
@Override public Map<String, Object> getDataHisByUserId(Integer userId){ Map<String, Object> map = new HashMap<>(); List<Date> xAxis = new ArrayList<>(); List<RtuAttribute> rtuAttributes = rtuAttributeMapper.getDataHisByUserId(userId); List<Map<String, Object>> seriesDatas = new ArrayList<>(); if (rtuAttributes != null && rtuAttributes.size() > 0) { for (RtuAttribute rtuAttribute : rtuAttributes) { //根據tagCode獲取所有的資料 List<DataHis> dataHisByTagCode = mapper.getDataHisByTagCode(rtuAttribute.getTagCode()); Map<String, Object> seriesData = new HashMap<>(); seriesData.put("name", rtuAttribute.getAttributeName()); seriesData.put("type", "line"); List<Double> chromaHisData = new ArrayList<>(); if (dataHisByTagCode != null && dataHisByTagCode.size() > 0) { for (DataHis dataHis : dataHisByTagCode) { chromaHisData.add(dataHis.getTagValue()); xAxis.add(dataHis.getTagTime()); } } seriesData.put("data", chromaHisData); seriesDatas.add(seriesData); } } map.put("xAxisData", xAxis); map.put("seriesDatas", seriesDatas); return map; }
var chromaHis = echarts.init(document.getElementById('chromaHis')); $.get("alter/datahis/getHisByUserId/"+userId,function (data) { var dataHis = data.data; optionHis = { title: { text: '歷史曲線' }, tooltip: { trigger: 'axis' }, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, xAxis: { type: 'category', boundaryGap: false, data:dataHis.xAxisData }, yAxis: { type: 'value' }, series: dataHis.seriesDatas }; chromaHis.setOption(optionHis, true); });
Hashtable使用
@Override
public Hashtable<String, List<DicItem>> getDicByCodes(String dictCodes,Integer userId, String orgManageDataCode,String orgDataCode, Integer orgLevel){
Hashtable<String,List<DicItem>> hashtable = new Hashtable<>();
String[] codes = dictCodes.split(",");
List<DicItem> dicItems = new ArrayList<>();
for(String code : codes){
dicItems = getDicByCode(code,userId,orgManageDataCode,orgDataCode,orgLevel);
if(dicItems != null){
hashtable.put(code, dicItems);
}
}
return hashtable;
}
2、對外提供的介面不同 Hashtable比HashMap多提供了elments() 和contains() 兩個方法。
elments() 方法繼承自Hashtable的父類Dictionnary。elements() 方法用於返回此Hashtable中的value的列舉。
contains()方法判斷該Hashtable是否包含傳入的value。它的作用與containsValue()一致。事實上,contansValue() 就只是呼叫了一下contains() 方法。 3、對Null key 和Null value的支援不同 Hashtable既不支援Null key也不支援Null value。Hashtable的put()方法的註釋中有說明。
當key為Null時,呼叫put() 方法,執行到下面這一步就會丟擲空指標異常。因為拿一個Null值去呼叫方法了。
當value為null值時,Hashtable對其做了限制,執行到下面這步也會丟擲空指標異常。
HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對應的值為null。當get()方法返回null值時,可能是 HashMap中沒有該鍵,也可能使該鍵所對應的值為null。因此,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵, 而應該用containsKey()方法來判斷。 4、執行緒安全性不同 Hashtable是執行緒安全的,它的每個方法中都加入了Synchronize方法。在多執行緒併發的環境下,可以直接使用Hashtable,不需要自己為它的方法實現同步
HashMap不是執行緒安全的,在多執行緒併發的環境下,可能會產生死鎖等問題。具體的原因在下一篇文章中會詳細進行分析。使用HashMap時就必須要自己增加同步處理,
雖然HashMap不是執行緒安全的,但是它的效率會比Hashtable要好很多。這樣設計是合理的。在我們的日常使用當中,大部分時間是單執行緒操作的。HashMap把這部分操作解放出來了。當需要多執行緒操作的時候可以使用執行緒安全的ConcurrentHashMap。ConcurrentHashMap雖然也是執行緒安全的,但是它的效率比Hashtable要高好多倍。因為ConcurrentHashMap使用了分段鎖,並不對整個資料進行鎖定。 5、初始容量大小和每次擴充容量大小的不同 Hashtable預設的初始大小為11,之後每次擴充,容量變為原來的2n+1。HashMap預設的初始化大小為16。之後每次擴充,容量變為原來的2倍。
建立時,如果給定了容量初始值,那麼Hashtable會直接使用你給定的大小,而HashMap會將其擴充為2的冪次方大小。也就是說Hashtable會盡量使用素數、奇數。而HashMap則總是使用2的冪作為雜湊表的大小。
之所以會有這樣的不同,是因為Hashtable和HashMap設計時的側重點不同。Hashtable的側重點是雜湊的結果更加均勻,使得雜湊衝突減少。當雜湊表的大小為素數時,簡單的取模雜湊的結果會更加均勻。而HashMap則更加關注hash的計算效率問題。在取模計算時,如果模數是2的冪,那麼我們可以直接使用位運算來得到結果,效率要大大高於做除法。HashMap為了加快hash的速度,將雜湊表的大小固定為了2的冪。當然這引入了雜湊分佈不均勻的問題,所以HashMap為解決這問題,又對hash演算法做了一些改動。這從而導致了Hashtable和HashMap的計算hash值的方法不同
6、計算hash值的方法不同 為了得到元素的位置,首先需要根據元素的 KEY計算出一個hash值,然後再用這個hash值來計算得到最終的位置。
Hashtable直接使用物件的hashCode。hashCode是JDK根據物件的地址或者字串或者數字算出來的int型別的數值。然後再使用除留餘數發來獲得最終的位置。
Hashtable在計算元素的位置時需要進行一次除法運算,而除法運算是比較耗時的。 HashMap為了提高計算效率,將雜湊表的大小固定為了2的冪,這樣在取模預算時,不需要做除法,只需要做位運算。位運算比除法的效率要高很多。
HashMap的效率雖然提高了,但是hash衝突卻也增加了。因為它得出的hash值的低位相同的概率比較高,而計算位運算
為了解決這個問題,HashMap重新根據hashcode計算hash值後,又對hash值做了一些運算來打散資料。使得取得的位置更加分散,從而減少了hash衝突。當然了,為了高效,HashMap只做了一些簡單的位處理。從而不至於把使用2 的冪次方帶來的效率提升給抵消掉。