Java HashMap的使用

      最近在編碼中經常用到HashMap,所得到的瞭解也僅限於《Java核心技術卷I》上面關於Map的簡單介紹(get、put方法),但是對其背後具體實現尚沒有了解。這個博文比較詳細的說明了源碼中HashMap的實現原理,java中HashMap詳解

       簡而言之就是一句關鍵話:當向 HashMap 中添加 key-value 對,由其 key 的 hashCode() 返回值決定該 key-value 對(就是 Entry 對象)的存儲位置。當兩個 Entry 對象的 key 的 hashCode() 返回值相同時,將由 key 通過 eqauls() 比較值決定是採用覆蓋行爲(返回 true),還是產生 Entry 鏈(返回 false)【注意key的hashcode相等並不是說key就相等,hashcode的計算是由初始化時桶的數目和裝填因子來決定,肯定存在hashcode值相等,但key值不相等的情況。另外key值相等的話,hashcod那麼肯定是相等的】。可以把value當做是key的附屬,在前面考慮key-value對存在於HashMap表何處時,完全是用key值在計算,entry鏈上也是各個key值不同但是key的hashcode值相同的節點。

       最近做OJ也碰到已到可以採用HashMap方法解決的。Problem 1203 - 找相同   題目的意思就是輸出出現次數超過一半的數,那麼就直接對每個數計數就是。 構建HashMap表,其中輸入的各個數字爲key,數字出現的次數爲value。 本題可以對每個輸入元素,先用Map的 V get(K key)方法獲得與鍵key(即每個輸入的數字)對應的值value,如果該數字是第一次輸入,那麼get方法返回的是null值;如果不是則放回其對應的value值,也就是這個數字已經出現的次數。 那麼就可以根據這個返回值來將包含這個數字的key-value對寫入Map中:get方法返回null,key-value對爲(數字,1);get方法返回的數字已經出現的次數 j,key-value對爲(數字, j+1),這種情況下寫入這個key-value對的時候,會覆蓋之前的key-value對(數字, j)。鍵必須是唯一的,不能對同一個鍵存放兩個值。當對同一個鍵兩個調用put(K kye, V value)方法時,後面的value會覆蓋前面的value,所以前面所說的 j+1 會覆蓋 j。

       構建完HashMap表之後,那麼表中的每個key就是輸入的各數字,key相對應的value值就是這個數字出現的次數,那麼調用int map.size() 方法就能夠獲得map中key值得數目,也就是這輸入的一串數字中,值各不相同的數字的個數。 此時構建Map表的entry視圖(調用map.entrySet()方法),用entry元素或者說是entry對象(key-value對)遍歷整個Map表,由於entry元素就存在getKey()和getValue()方法,就很容易獲得每一個key-value對的key值、value值,遍歷後返回最大value值即可。雖然在Map中,由key值獲得value值是簡單的,直接調用V get(K key)方法即可,但是由於存在不同的key值可能對應值相同的value,那麼不能直接 K get(V value) 方法直接返回value所對應的key值(也不直接存在這樣的方法)。 要獲得value對應的key值,也只能用entry元素遍歷整個Map表,value值等於前面返回的最大value的entry元素(key-value對),就調用 getKey()方法獲得value值對應的 key值。


    附錄代碼(沒有考慮提交,輸入項採用main入口函數的string參數)

package T_1203;

// 題目的意思是要求輸出次數過半的元素,可以採用Map來做統計各個數出現的次數

import java.util.* ;

public class Main
{    
    public static void main(String args[]) 
    {
        Map<String, Integer> m = new HashMap<String, Integer>();
        
        for(int i=0 ;i<args.length ;i++) 
        {
            int j = (Integer)m.get(args[i]) == null ? 0 : (Integer)m.get(args[i]) ;
            m.put(args[i] , (j == 0 ? 1 : j + 1)) ; //新出現數字則加入(數字,1),以前已出現數字就用(數字,j+1)覆蓋之前的(數字,j)
        }
        
        Integer max = 0;
        
        for(Map.Entry<String,Integer> entry: m.entrySet())  //構建map表的entry視圖,遍歷map的所有key——value對,獲得value最大值
        {
        	if(m.get(entry.getKey())> max)
        		max = m.get(entry.getKey());        	
        }
        List<String> list = new ArrayList<String>();
        
        for(Map.Entry<String, Integer> entry:m.entrySet())  //既然不直接存在像 V get(K key)這樣的K get(V value)這樣的方法,那麼就直接遍歷整個map表
        {
        	if(max == entry.getValue())
        		list.add(entry.getKey());
        }
        System.out.println(list.toString());
        System.out.println(m) ;
    	
    } 
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章