HashMap源代码

来源:互联网 发布:工厂跟单软件 编辑:程序博客网 时间:2024/05/22 04:34

HashMap是最常使用的类,所以学习它的源码很重要。

HashMap的结构如下:


/**     * The table, resized as necessary. Length MUST Always be a power of two.     */    transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

由Entry[] table负责存储数据。其中Entry是它的静态内部类,Entry结构如下:

static class Entry<K,V> implements Map.Entry<K,V> {        final K key;        V value;        Entry<K,V> next;        int hash;
很明显可以看出,Entry就是一个链表,所以HashMap的结构其实就是一个数组,然后数组里面的元素是链表,如下图所示:


HashMap中最常使用的方法是get和put,首先看下put方法

public V put(K key, V value) {        if (table == EMPTY_TABLE) {            inflateTable(threshold);        }        if (key == null)//允许null key            return putForNullKey(value);        int hash = hash(key);//对key进行hash        int i = indexFor(hash, table.length);//通过hash值找到对应存储位置        for (Entry<K,V> e = table[i]; e != null; e = e.next) {//遍历链元素,查找链表中有没有相同的key,如果有就替换            Object k;            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {//先比较hash,如果hash值相等,再比较具体的key值                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }        modCount++;        addEntry(hash, key, value, i);//如果没有key,就做插入        return null;    }

private V putForNullKey(V value) {        for (Entry<K,V> e = table[0]; e != null; e = e.next) {//大体过程与普通put操作一样,只不过要注意如果是null key就存储在0位置            if (e.key == null) {                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }        modCount++;        addEntry(0, null, value, 0);        return null;    }

get方法:

public V get(Object key) {        if (key == null)            return getForNullKey();        Entry<K,V> entry = getEntry(key);        return null == entry ? null : entry.getValue();    }
private V getForNullKey() {        if (size == 0) {            return null;        }        for (Entry<K,V> e = table[0]; e != null; e = e.next) {//没什么好说的,就要注意null key的值存储在0位置            if (e.key == null)                return e.value;        }        return null;    }
final Entry<K,V> getEntry(Object key) {        if (size == 0) {            return null;        }        int hash = (key == null) ? 0 : hash(key);//再次证明null key 在0位置        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;    }






0 0
原创粉丝点击