<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 28,  comments - 15,  trackbacks - 0
        HashMap內(nèi)部有一個Entry數(shù)組,可以稱之為hash table。HashMap的默認(rèn)構(gòu)造值為初始容量為16,負(fù)載因子為0.75,閥值(初始容量*負(fù)載因子)為12。其默認(rèn)構(gòu)造子如下:
    public class HashMap<K,V>
        
    extends AbstractMap<K,V>
        
    implements Map<K,V>, Cloneable, Serializable
    {

        
    /**
         * The default initial capacity - MUST be a power of two.
         
    */

        
    static final int DEFAULT_INITIAL_CAPACITY = 16;

        
    /**
         * The maximum capacity, used if a higher value is implicitly specified
         * by either of the constructors with arguments.
         * MUST be a power of two <= 1<<30.
         * 
         * 如果一個較大的值被任意一個帶有參數(shù)的構(gòu)造器指定,最大容量被使用。
         
    */

        
    static final int MAXIMUM_CAPACITY = 1 << 30;   //1073741824

        
    /**
         * The load factor used when none specified in constructor.
         
    */

        
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

        
    /**
         * The table, resized as necessary. Length MUST Always be a power of two.
         
    */

        
    transient Entry[] table;

        
    /**
         * The number of key-value mappings contained in this map.
         
    */

        
    transient int size;

        
    /**
         * The next size value at which to resize (capacity * load factor).
         * 
         * 下一個用來調(diào)整的大小值
         * 
    @serial
         
    */

        
    int threshold;

        
    /**
         * The load factor for the hash table.
         *
         * 
    @serial
         
    */

        
    final float loadFactor;

    public HashMap() {
            
    this.loadFactor = DEFAULT_LOAD_FACTOR;  
            threshold 
    = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
            table 
    = new Entry[DEFAULT_INITIAL_CAPACITY];  //默認(rèn)情況下,以容量為16構(gòu)建Entry數(shù)組
            init();
        }


    put方法分析:
     <1>HashMap首先判斷key是否為null,如果為null,
        <1.1>HashMap從hash table中第0個位置的Entry,如果該Entry不等于null且entry.key也不為null,當(dāng)前value覆蓋entry的value。
        <1.2>否則,在hash table[0]處創(chuàng)建新的key=null的Entry。
     <2>
        接下來,以key的hashcode做hash運算,獲得hash值。該hash值與hash table的長度-1做與操作,獲得key在當(dāng)前hash table中的位置索引。
        然后檢查在該索引位置是否存在Entry對象,如果存在,且該Entry對象的key的hash值與上面計算的hash值相等,且entry的key與傳入的key相等或者key.equals(entry.key),那么以當(dāng)前的value值覆蓋舊值,并返回舊值。
        如果hash table中不存在key所指定的Entry,那么就要增加新的Entry。在增加Entry后,要檢查容量是否已經(jīng)達(dá)到閥值,如果達(dá)到閥值,就以當(dāng)前hash table的長度的2倍擴展。同時要重新計算entry在新的hash table中的索引位置。注意,由于hash計算可能導(dǎo)致key的hash值可能是重復(fù)的,HashMap采用鏈表的方式解決hash值沖突的問題,另外一種解決方法是開放地址法。
        以下是put方法部分代碼:
    public V put(K key, V value) {
            
    if (key == null)
                
    return putForNullKey(value);
            
            
    /*這里對key的hasCode做hash*/
            
    int hash = hash(key.hashCode());
            
    /*通過hash值與hash表的長度減1做與操作獲取hash表的索引值*/
            
    int i = indexFor(hash, table.length);
            
    /*由于hash可能重復(fù),導(dǎo)致獲取重復(fù)的索引值,這里通過判斷傳入的key的has值與當(dāng)前節(jié)點的key的has值是否相等,且key相等或者equals相等,來用新的value替換舊值,并返回舊值*/
            
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
                Object k;
                
    if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                    V oldValue 
    = e.value;
                    e.value 
    = value;
                    e.recordAccess(
    this);
                    
    return oldValue;
                }

            }

            
            
    /*否則增加節(jié)點*/
            modCount
    ++;
            addEntry(hash, key, value, i);
            
    return null;
        }


    處理key為空的情況:

     private V putForNullKey(V value) {
            
    /*從0桶查找key為null的Entry。如果桶中有null的Entry,那么把當(dāng)前新的值設(shè)置到Entry中,并返回舊值*/
            
    for (Entry<K,V> e = table[0]; e != null; e = e.next) {
                
    if (e.key == null{
                    V oldValue 
    = e.value;
                    e.value 
    = value;
                    e.recordAccess(
    this);
                    
    return oldValue;
                }

            }

            
            modCount
    ++;
            addEntry(
    0null, value, 0);
            
    return null;
        }

    計算key的hash值與計算key所應(yīng)處在hash table中的位置:

    static int hash(int h) {
            
    // This function ensures that hashCodes that differ only by
            
    // constant multiples at each bit position have a bounded
            
    // number of collisions (approximately 8 at default load factor).
            h ^= (h >>> 20^ (h >>> 12);
            
    return h ^ (h >>> 7^ (h >>> 4);
        }


        
    /**
         * Returns index for hash code h.
         
    */

        
    static int indexFor(int h, int length) {
            
    return h & (length-1);
        }

    增加entry節(jié)點以及擴容:

     void addEntry(int hash, K key, V value, int bucketIndex) {
            Entry
    <K,V> e = table[bucketIndex];//臨時存儲指定桶索引的Entry
            table[bucketIndex] = new Entry<K,V>(hash, key, value, e);//在指定桶索引位置創(chuàng)建新的Entry,并自動把原桶索引的Entry作為當(dāng)前Entry的next
            /*當(dāng)size達(dá)到閥值(當(dāng)前容量*負(fù)載因子=threshold),需要擴容*/
            
    if (size++ >= threshold)
                resize(
    2 * table.length);
        }

    ------------------------------------------------

     void resize(int newCapacity) {
            Entry[] oldTable 
    = table;
            
    int oldCapacity = oldTable.length;
            
    /*如果就有容量達(dá)到默認(rèn)的的容量最大值(2的30次方),threshold設(shè)為整形的最大值(2的31次方-1)*/
            
    if (oldCapacity == MAXIMUM_CAPACITY) {
                threshold 
    = Integer.MAX_VALUE;
                
    return;
            }


            Entry[] newTable 
    = new Entry[newCapacity];
            
    /*這里把源hash表中的數(shù)據(jù)拷貝到新的hash表中,注意的是,源hash表中鏈表到新hash表中由頭變成了尾*/
            transfer(newTable);
            table 
    = newTable;
            
    /*設(shè)置擴容后新的閥值*/
            threshold 
    = (int)(newCapacity * loadFactor);
        }


    get方法分析:
        當(dāng)調(diào)用get方法時,HashMap首先判斷key是否為null,如果為null,其hash值為0,否則通過hash算法計算。
        接下來,通過該hash值與hash table的長度-1做與操作,獲得key在hash table中的索引。如果entry不等null,且該傳入key的hash值與entry的hash值相等,且key==entry.key或者key.equals(entry.key),則返回該entry.value.否則返回null.

        final Entry<K,V> getEntry(Object key) {
            
    int hash = (key == null? 0 : hash(key.hashCode());
            
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
                 e 
    != null;
                 e 
    = e.next) {
                Object k;
                
    if (e.hash == hash &&
                    ((k 
    = e.key) == key || (key != null && key.equals(k))))
                    
    return e;
            }

            
    return null;
        }







     


     

     

     

     

     

     

     

     

     

     

     

    posted on 2012-02-13 14:42 zhangxl 閱讀(428) 評論(0)  編輯  收藏 所屬分類: JDK

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
    博客園   IT新聞   Chat2DB   C++博客   博問  
     
    <2012年2月>
    2930311234
    567891011
    12131415161718
    19202122232425
    26272829123
    45678910

    常用鏈接

    留言簿(1)

    隨筆分類(17)

    隨筆檔案(28)

    文章分類(30)

    文章檔案(30)

    相冊

    收藏夾(2)

    hibernate

    java基礎(chǔ)

    mysql

    xml

    關(guān)注

    壓力測試

    算法

    最新隨筆

    搜索

    •  

    積分與排名

    • 積分 - 96772
    • 排名 - 600

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 在线免费观看色片| 麻豆最新国产剧情AV原创免费| 国产午夜影视大全免费观看| 亚洲免费福利视频| 久久精品免费全国观看国产| 亚洲免费人成视频观看| av无码久久久久不卡免费网站| 亚洲最大成人网色香蕉| 毛片免费观看视频| 亚洲AV成人精品一区二区三区| 国产成人aaa在线视频免费观看| 久久精品国产亚洲AV电影网| 免费国产怡红院在线观看| 一个人看的免费观看日本视频www 一个人看的免费视频www在线高清动漫 | 亚洲成年人电影在线观看| 黄页网站免费观看| 亚洲av日韩av永久无码电影| 亚洲AV伊人久久青青草原| 中文字幕免费在线播放| 久久亚洲AV无码精品色午夜麻豆| 日本最新免费网站| 国产精品高清视亚洲一区二区| 国产精品公开免费视频| 羞羞视频免费网站在线看| 久久精品国产精品亚洲蜜月| 成人免费观看一区二区| 亚洲AV无码专区在线观看成人| 亚洲av无码乱码在线观看野外| 国产福利在线观看永久免费| 亚洲国产精品久久久久| 少妇高潮太爽了在线观看免费| 国产成人综合久久精品亚洲| 亚洲老妈激情一区二区三区| 无码精品A∨在线观看免费| 亚洲AV网一区二区三区| 亚洲av综合av一区| 在线播放免费人成视频在线观看 | 精品国产_亚洲人成在线| 国产亚洲av片在线观看16女人| 国产精品久久久久久久久免费| 亚洲国产成人AV网站|