Java7 hashmap

JDK1.7中的hashmap。

HashMap繼承自AbstractMap,實現了Map、Cloneable、Serializable接口。

默認初始容量爲:1<<4 即 16

最大容量爲:1<<30 即2的30次方

默認負載因子:0.75

Entry<K,V>數組。

每個Entry的屬性:

final K key;
V value;
Entry<K,V> next;
int hash;

hashmap put方法

public V put(K key, V value){
    if(table == EMPTY_TABLE){
        inflateTable(thresold);
    }
    if(key==null){
        return putForNullKey(value);
    }
    int hash=hash(key);
    int i = indexFor(hash,table.length);
    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;
        }
    }
    modCount++;
    addEntry(hash,key,value,i);
    return null;
}

put方法流程:

(1)如果table爲空,進行初始化。

(2)如果keyt爲null,調用putForNullKey()方法

(3)獲取key的hash

(4)根據hash值獲取當前節點所在的index,使用的方式是i=hash&(table.length-1);

(5)如果table[i]的位置不爲null,對鏈表進行遍歷,找到hash和key值都相等的節點,然後覆蓋原來的value,並返回舊的value;

(6)如果對應位置爲null,或者通過遍歷找不到該節點,則modCount++並調用addEntry()。

addEntry()方法

void addEntry(int hash, K key, V value, int bucketIndex){
    if((size>=threshold)&&(null!=table[bucketIndex])){
        resize(2*table.length);
        hash=(null!=key)?hash(key):0;
        bucketIndex=indexFor(hash,table.length);
    }
    createEntry(hash,key,value,bucketIndex);
}

如果size已經超過了threshold並且對應位置不爲空,resizehashmap。然後重新計算hash和桶位置。並創建新的entry。在創建新節點之後,將size++;

hashmap get方法

key爲空,調用getForNullKey。不爲空,調用getEntry。通過key計算對應的桶位置,並遍歷該位置的鏈表獲取節點。、

hashmap resize()方法

void resize(int newCapacity){
    Entry[] oldTable=table;
    int oldCapacity=oldTable.length;
    if(oldCapacity==MAXIMUM_CAPACITY){
        threshold=Integer.MAX_VALUE;
        return;
    }
    Entry[] newTable=new Entry[newCapacity];
    transfer(newTable,initHashSeedAsNeeded(newCapacity));
    table=newTable;
    threshold=(int)Math.min(newCapacity*loadFactor,MAXIMUM_CAPACITY+1);
}

transfer方法

void transfer(Entry[] newTable, boolean rehash){
    int newCapacity=newTable.length;
    for(Entry<K,V> e: table){
        while(null!=e){
            Entry<K,V> next=e.next;
            if(rehash){
                e.hash=null==e.key?0:hash(key);
            }
            int i=indexFor(e.hash,newCapacity);
            e.next=newTable[i];
            newTable[i]=e;
            e=next;
     }
}

resize方法流程:

新建一個長度爲原來兩倍的數組,將原數組中的內容rehash到新的數組中,然後指向新的table。

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