1. 程式人生 > >HashMap與Hashtable的使用

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 的冪次方帶來的效率提升給抵消掉。è¿éåå¾çæè¿°