HashMap源码解读

来源:互联网 发布:编程机器人手机游戏 编辑:程序博客网 时间:2024/06/05 05:15

HashMap是基于哈希表的Map接口实现,以key-value的形式保存数据。在HashMap中,系统会根据hash算法来计算key-value的存储位置。使用时,我们可以通过key值快速的存取value值。下面就一起来看一下HashMap的源码:
一、类定义

public class HashMap<K,V>    extends AbstractMap<K,V>    implements Map<K,V>, Cloneable, Serializable

HashMap实现了Map接口,继承AbstractMap。Map接口定义key-value的映射规则,AbstractMap类提供Map接口的主要实现。
二、一些变量

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

默认的初始容量—必须是2的幂,初始默认值是16。

static final int MAXIMUM_CAPACITY = 1 << 30;

最大容量,如果通过构造函数传入一个更大的值,则使用最大容量。必须是2的幂,最大值是1073741824。

static final float DEFAULT_LOAD_FACTOR = 0.75f;

当构造函数中没有指定时,使用默认负载因子0.75。

int threshold;

调整下一个值的大小(容量*负载因子)

三、构造函数

public HashMap(int initialCapacity, float loadFactor)

构造一个带指定初始容量和负载因子的空HashMap

public HashMap(int initialCapacity)

构造一个带指定初始容量和默认负载因子的(0.75)的空HashMap

public HashMap() 

构造一个带初始容量(16)和默认负载因子(0.75)的空HashMap

public HashMap(Map<? extends K, ? extends V> m)

构造一个与指定Map具有相同映射新HashMap。HashMap是使用默认负载因子(0.75)创建的,初始容量足以保留指定映射中的映射。
构造函数中反复提到的两个参数:初始容量和负载因子。这两个参数是影响HashMap性能的重要参数,其中容量表示哈希表中桶的数量,初始容量是创建哈希表时的容量,加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度,它衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之越小。对于使用链表法的散列表来说,查找一个元素的平均时间是O(1+a),因此如果负载因子越大,对空间的利用更充分,然而后果是查找效率的降低;如果负载因子太小,那么散列表的数据将过于稀疏,对空间造成严重浪费。系统默认负载因子为0.75,一般情况下我们是无需修改的。
四、主要函数解读
1.构造函数

public HashMap(int initialCapacity, float loadFactor) {        //初始容量不能小于0    if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal initial capacity: " initialCapacity);        //初始容量不能大于最大容量,即不能大于2^30。若大于,以最大容量为准。    if (initialCapacity > MAXIMUM_CAPACITY)            initialCapacity = MAXIMUM_CAPACITY;    //负载因子不能小于0        if (loadFactor <= 0 || Float.isNaN(loadFactor))            throw new IllegalArgumentException("Illegal load factor: " +loadFactor);    this.loadFactor = loadFactor;    //设置HashMap的容量极限,当HashMap的容量达到该极限时就会进行扩容操作        threshold = initialCapacity;        init();    }

2.hash(Object k)

final int hash(Object k) {        int h = hashSeed;        if (0 != h && k instanceof String) {            return sun.misc.Hashing.stringHash32((String) k);        }        h ^= k.hashCode();        //此函数确保仅在每个位位置处不同的常数倍数的哈希码具有有限数量的冲突    //(在默认负载因子下约为8)        h ^= (h >>> 20) ^ (h >>> 12);        return h ^ (h >>> 7) ^ (h >>> 4);    }

3.get()

public V get(Object key) {    //判断key是否为空,为空调用getForNullKey()方法返回对应的值。        if (key == null)            return getForNullKey();    //获取与查找key相同的key,返回对应的value值。        Entry<K,V> entry = getEntry(key);        return null == entry ? null : entry.getValue();    }

4.containsKey(Object key)

public boolean containsKey(Object key) {        //若HashMap中包含此key,则返回true。    return getEntry(key) != null;    }

5.put(K key, V value)

public V put(K key, V value) {    //判断当前HashMap是否为空,若为空,执行扩容。        if (table == EMPTY_TABLE) {            inflateTable(threshold);        }    //判断当前key值是否为空,若为空,返回putForNullKey(value)对应的值。        if (key == null)            return putForNullKey(value);    //生成一个新的hash码。        int hash = hash(key);    //探测hash表,将key-value值存入。        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;    }

6.remove(Object key)

public V remove(Object key) {    //调用removeEntryForKey()函数,删除对应的key-value值。        Entry<K,V> e = removeEntryForKey(key);        return (e == null ? null : e.value);    }

7.clone()

//返回此HashMap实例的浅复制:键和值本身未复制。public Object clone() {        HashMap<K,V> result = null;        try {            result = (HashMap<K,V>)super.clone();        } catch (CloneNotSupportedException e) {        }        if (result.table != EMPTY_TABLE) {            result.inflateTable(Math.min(                (int) Math.min(                    size * Math.min(1 / loadFactor, 4.0f),                    // we have limits...                    HashMap.MAXIMUM_CAPACITY),               table.length));        }        result.entrySet = null;        result.modCount = 0;        result.size = 0;        result.init();        result.putAllForCreate(this);        return result;    }
1 0
原创粉丝点击