HashMap源码

来源:互联网 发布:烟灶套装 知乎 编辑:程序博客网 时间:2024/06/06 04:01

1.HashMap实现了Map接口,继承AbstractMap。

  初始容量,加载因子。这两个参数是影响HashMap性能的重要参数,其中容量表示哈希表中桶的数量,初始容量是创建哈希表时的容量,加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度,它衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之愈小。

2.数据结构

 HashMap底层实现还是数组,只是数组的每一项都是一条链表

 

3.源码

package java.util;import java.io.*;public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {private static final long serialVersionUID = 362498820763181265L;// 系统默认初始容量,必须是2的n次幂,这是出于优化考虑的      static final int DEFAULT_INITIAL_CAPACITY = 16;// 系统默认最大容量      static final int MAXIMUM_CAPACITY = 1 << 30;// 默认的加载因子,可在构造函数中指定     static final float DEFAULT_LOAD_FACTOR = 0.75f;// 用于存储的表,长度可以调整,且必须是2的n次幂    transient Entry[] table;// 当前map的key-value映射数,也就是当前size    transient int size;// 阈值,当HashMap当前size到达这个阈值时,HashMap就需要扩大一倍了。      int threshold;// 加载因子,final常量,只能被赋值一次,赋值后值不再改变。    final float loadFactor;// 用于确保使用迭代器的时候,HashMap并未进行更改     transient volatile int modCount;private transient Set<Map.Entry<K,V>> entrySet = null;/** *@param initialCapacity 初始容量 *@param loadFactor 初始加载因子 */    public HashMap(int initialCapacity, float loadFactor) {        if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal initial capacity: " +  initialCapacity);        if (initialCapacity > MAXIMUM_CAPACITY)            initialCapacity = MAXIMUM_CAPACITY;        if (loadFactor <= 0 || Float.isNaN(loadFactor))            throw new IllegalArgumentException("Illegal load factor: " + loadFactor);        // 寻找一个2的k次幂capacity恰好大于initialCapacity ,保证容量是2的幂        int capacity = 1;        while (capacity < initialCapacity)            capacity <<= 1;        this.loadFactor = loadFactor;// 设置阀值        threshold = (int)(capacity * loadFactor);        table = new Entry[capacity];        init();    }/** * 创建默认加载因子0.75的HashMap */    public HashMap(int initialCapacity) {        this(initialCapacity, DEFAULT_LOAD_FACTOR);    }/** * 创建默认加载因子0.75, 默认初始容量16的HashMap*/    public HashMap() {        this.loadFactor = DEFAULT_LOAD_FACTOR;        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);        table = new Entry[DEFAULT_INITIAL_CAPACITY];        init();    }/** * 根据m创建HashMap */    public HashMap(Map<? extends K, ? extends V> m) {        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);        putAllForCreate(m);    }private void putAllForCreate(Map<? extends K, ? extends V> m) {        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {            Map.Entry<? extends K, ? extends V> e = i.next();            putForCreate(e.getKey(), e.getValue());        }    }/** * @param key 键 * @param value 值 */    private void putForCreate(K key, V value) {        int hash = (key == null) ? 0 : hash(key.hashCode());        int i = indexFor(hash, table.length);// 已存在key就覆盖        for (Entry<K,V> e = table[i]; e != null; e = e.next) {// 循环链表            Object k;            if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {                e.value = value;                return;            }        }        createEntry(hash, key, value, i);    }/** * 创建Entry,类似addEntry, 但是不需要调整表的大小 * @param hash key的哈希值 * @param key 键 * @param value 值 * @param bucketIndex entry在数组table中的索引*/    void createEntry(int hash, K key, V value, int bucketIndex) {Entry<K,V> e = table[bucketIndex];        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);        size++;    }    void init() {    }    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);    }/** * 当数组长度为2的n次幂的时候,不同的key算得得index相同的几率较小, * 那么数据在数组上分布就比较均匀,也就是说碰撞的几率小, * 相对的,查询的时候就不用遍历某个位置上的链表,这样查询效率也就较高了。  * @param h key值的哈希值求hash() * @param length hashmap长度 */    static int indexFor(int h, int length) {        return h & (length-1);    }public void putAll(Map<? extends K, ? extends V> m) {        int numKeysToBeAdded = m.size();        if (numKeysToBeAdded == 0)            return;        if (numKeysToBeAdded > threshold) {            int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);            if (targetCapacity > MAXIMUM_CAPACITY)                targetCapacity = MAXIMUM_CAPACITY;            int newCapacity = table.length;            while (newCapacity < targetCapacity)                newCapacity <<= 1;            if (newCapacity > table.length)                resize(newCapacity);        }        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {            Map.Entry<? extends K, ? extends V> e = i.next();            put(e.getKey(), e.getValue());        }    }/** * 添加一个entry * @param key 键 * @param value 值 */    public V put(K key, V value) {        if (key == null)            return putForNullKey(value);        int hash = hash(key.hashCode());        int i = indexFor(hash, table.length);        for (Entry<K,V> e = table[i]; e != null; e = e.next) {// 数组索引i处Entry存在            Object k;            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {// key值存在,则覆盖,返回旧数据value                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }// 记录hashmap被修改了        modCount++;        addEntry(hash, key, value, i);        return null;    }/** * key值为null */private V putForNullKey(V value) {        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(0, null, value, 0);        return null;    }/** * 新增一个entry * @param hash key的哈希值求hash() * @param key 键 * @param value 值 * @param bucketIndex entry在数组table中的索引 */    void addEntry(int hash, K key, V value, int bucketIndex) {Entry<K,V> e = table[bucketIndex];        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);// 当hashmap个数超过阀值,需要扩容        if (size++ >= threshold)            resize(2 * table.length);    }/** * hashmap调整大小 * @param newCapacity 新的容量大小 */    void resize(int newCapacity) {        Entry[] oldTable = table;        int oldCapacity = oldTable.length;        if (oldCapacity == MAXIMUM_CAPACITY) {// 如果当前大小oldCapacity等于最大值,设置阀值为(2<<31 -1),返回            threshold = Integer.MAX_VALUE;            return;        }        Entry[] newTable = new Entry[newCapacity];        transfer(newTable);        table = newTable;        threshold = (int)(newCapacity * loadFactor);// 新阀值    }/** * 将当前table中的所有entry赋值到新newTable * @param newTable 新table */    void transfer(Entry[] newTable) {        Entry[] src = table;        int newCapacity = newTable.length;        for (int j = 0; j < src.length; j++) {            Entry<K,V> e = src[j];            if (e != null) {                src[j] = null;// 源table中索引j处置null                do {                    Entry<K,V> next = e.next;                    int i = indexFor(e.hash, newCapacity);                    e.next = newTable[i];                    newTable[i] = e;                    e = next;                } while (e != null);            }        }    }public V get(Object key) {        if (key == null)            return getForNullKey();        int hash = 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.equals(k)))                return e.value;        }        return null;    }/** * 返回key=null的value */    private V getForNullKey() {        for (Entry<K,V> e = table[0]; e != null; e = e.next) {            if (e.key == null)                return e.value;        }        return null;    }/** * 返回key值对应的Entry对象 * @param key 键 */    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;    }    public V remove(Object key) {        Entry<K,V> e = removeEntryForKey(key);        return (e == null ? null : e.value);    }    final Entry<K,V> removeEntryForKey(Object key) {        int hash = (key == null) ? 0 : hash(key.hashCode());        int i = indexFor(hash, table.length);        Entry<K,V> prev = table[i];        Entry<K,V> e = prev;        while (e != null) {            Entry<K,V> next = e.next;            Object k;            if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {                modCount++;                size--;                if (prev == e)                    table[i] = next;                else                    prev.next = next;                e.recordRemoval(this);                return e;            }            prev = e;            e = next;        }        return e;    }    public int size() {        return size;    }    public boolean isEmpty() {        return size == 0;    }    public void clear() {        modCount++;        Entry[] tab = table;        for (int i = 0; i < tab.length; i++)            tab[i] = null;        size = 0;    }    public boolean containsKey(Object key) {        return getEntry(key) != null;    }    public boolean containsValue(Object value) {if (value == null)return containsNullValue();Entry[] tab = table;        for (int i = 0; i < tab.length ; i++)            for (Entry e = tab[i] ; e != null ; e = e.next)                if (value.equals(e.value))                    return true;return false;    }    private boolean containsNullValue() {Entry[] tab = table;        for (int i = 0; i < tab.length ; i++)            for (Entry e = tab[i] ; e != null ; e = e.next)                if (e.value == null)                    return true;return false;    }    final Entry<K,V> removeMapping(Object o) {        if (!(o instanceof Map.Entry))            return null;        Map.Entry<K,V> entry = (Map.Entry<K,V>) o;        Object key = entry.getKey();        int hash = (key == null) ? 0 : hash(key.hashCode());        int i = indexFor(hash, table.length);        Entry<K,V> prev = table[i];        Entry<K,V> e = prev;        while (e != null) {            Entry<K,V> next = e.next;            if (e.hash == hash && e.equals(entry)) {                modCount++;                size--;                if (prev == e)                    table[i] = next;                else                    prev.next = next;                e.recordRemoval(this);                return e;            }            prev = e;            e = next;        }        return e;    }    public Object clone() {        HashMap<K,V> result = null;try {result = (HashMap<K,V>)super.clone();} catch (CloneNotSupportedException e) {// assert false;}        result.table = new Entry[table.length];        result.entrySet = null;        result.modCount = 0;        result.size = 0;        result.init();        result.putAllForCreate(this);        return result;    }/** * Entry对象 */    static class Entry<K,V> implements Map.Entry<K,V> {        final K key;        V value;        Entry<K,V> next;        final int hash;        /**         * Creates new entry. * @param h Entry在table中的索引 * @param k 键 * @param v 值 * @param n 当前Entry的下一个Entry         */        Entry(int h, K k, V v, Entry<K,V> n) {            value = v;            next = n;            key = k;            hash = h;        }        public final K getKey() {            return key;        }        public final V getValue() {            return value;        }        public final V setValue(V newValue) {V oldValue = value;            value = newValue;            return oldValue;        }        public final boolean equals(Object o) {            if (!(o instanceof Map.Entry))                return false;            Map.Entry e = (Map.Entry)o;            Object k1 = getKey();            Object k2 = e.getKey();            if (k1 == k2 || (k1 != null && k1.equals(k2))) {                Object v1 = getValue();                Object v2 = e.getValue();                if (v1 == v2 || (v1 != null && v1.equals(v2)))                    return true;            }            return false;        }        public final int hashCode() {            return (key==null   ? 0 : key.hashCode()) ^ (value==null ? 0 : value.hashCode());        }        public final String toString() {            return getKey() + "=" + getValue();        }        /**         * This method is invoked whenever the value in an entry is         * overwritten by an invocation of put(k,v) for a key k that's already         * in the HashMap.         */        void recordAccess(HashMap<K,V> m) {        }        /**         * This method is invoked whenever the entry is         * removed from the table.         */        void recordRemoval(HashMap<K,V> m) {        }    }/** * key值的集合 */    public Set<K> keySet() {        Set<K> ks = keySet;        return (ks != null ? ks : (keySet = new KeySet()));    }    private final class KeySet extends AbstractSet<K> {        public Iterator<K> iterator() {            return newKeyIterator();        }        public int size() {            return size;        }        public boolean contains(Object o) {            return containsKey(o);        }        public boolean remove(Object o) {            return HashMap.this.removeEntryForKey(o) != null;        }        public void clear() {            HashMap.this.clear();        }    }    Iterator<K> newKeyIterator()   {        return new KeyIterator();    }    private final class KeyIterator extends HashIterator<K> {        public K next() {            return nextEntry().getKey();        }    }/** * value值的集合 */    public Collection<V> values() {        Collection<V> vs = values;        return (vs != null ? vs : (values = new Values()));    }    private final class Values extends AbstractCollection<V> {        public Iterator<V> iterator() {            return newValueIterator();        }        public int size() {            return size;        }        public boolean contains(Object o) {            return containsValue(o);        }        public void clear() {            HashMap.this.clear();        }    }    Iterator<V> newValueIterator()   {        return new ValueIterator();    }    private final class ValueIterator extends HashIterator<V> {        public V next() {            return nextEntry().value;        }    }/** * entry对象的集合 */    public Set<Map.Entry<K,V>> entrySet() {return entrySet0();    }    private Set<Map.Entry<K,V>> entrySet0() {        Set<Map.Entry<K,V>> es = entrySet;        return es != null ? es : (entrySet = new EntrySet());    }    private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {        public Iterator<Map.Entry<K,V>> iterator() {            return newEntryIterator();        }        public boolean contains(Object o) {            if (!(o instanceof Map.Entry))                return false;            Map.Entry<K,V> e = (Map.Entry<K,V>) o;            Entry<K,V> candidate = getEntry(e.getKey());            return candidate != null && candidate.equals(e);        }        public boolean remove(Object o) {            return removeMapping(o) != null;        }        public int size() {            return size;        }        public void clear() {            HashMap.this.clear();        }    }Iterator<Map.Entry<K,V>> newEntryIterator()   {        return new EntryIterator();    }/** * 继承抽象类HashIterator */private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {        public Map.Entry<K,V> next() {            return nextEntry();        }    }/** * 迭代器抽象类 */private abstract class HashIterator<E> implements Iterator<E> {Entry<K,V> current;// current entry        Entry<K,V> next;// next entry to return        int expectedModCount;// For fast-fail        int index;// current slot        HashIterator() {// 期望值,当一个线程在调用hashmap时,另一个线程修改了hashmap,这时modCount改变了            expectedModCount = modCount;            if (size > 0) { // advance to first entry                Entry[] t = table;/** * 找到数组中第一个不是指向null的那个元素,将这个元素存入next中, * 同时index指向这个数组元素的下一个下标 */                while (index < t.length && (next = t[index++]) == null);            }        }        public final boolean hasNext() {            return next != null;        }/** * 首先查看当前“链表”是否已到结尾, * 若还没到,则next直接指向它的下一个”结点“; * 若已到”链表“结尾,则需要找到table数组中下一个不是指向空”链表“的那个元素,使next更新为”链表“首结点,同时更新index。 */final Entry<K,V> nextEntry() {/** * 判断HashMap是否在内部或被其它线程修改,如果modCount和expectedModCount值不一样, * 证明有其他线程在修改HashMap的结构,会抛出异常 * 所以HashMap的put、remove等操作都有modCount++的计算。 */if (modCount != expectedModCount)  throw new ConcurrentModificationException();Entry<K,V> e = next;if (e == null)throw new NoSuchElementException();if ((next = e.next) == null) {// 链表到尾了Entry[] t = table;while (index < t.length && (next = t[index++]) == null);}current = e;return e;}        public void remove() {            if (current == null)                throw new IllegalStateException();            if (modCount != expectedModCount)                throw new ConcurrentModificationException();            Object k = current.key;            current = null;// HashMap.this是HashIterator外围类的引用            HashMap.this.removeEntryForKey(k);            expectedModCount = modCount;        }    }/** * 输出到对象输出流s中 */    private void writeObject(java.io.ObjectOutputStream s) throws IOException {Iterator<Map.Entry<K,V>> i = (size > 0) ? entrySet0().iterator() : null;// 将当前类的非静态和非瞬态字段(阀值threshold,加载因子loadfactor)写入此流s.defaultWriteObject();// 写入table的大小s.writeInt(table.length);// 写入entry的个数s.writeInt(size);        // Write out keys and values (alternating)if (i != null) {while (i.hasNext()) {Map.Entry<K,V> e = i.next();s.writeObject(e.getKey());s.writeObject(e.getValue());}        }    }/** * 从对象输入流s重新构建 */    private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {// 读入阈值threshold,加载因子loadfactor和任何隐藏的东西s.defaultReadObject();// 读取table的数量numBuckets并分配table阵列;int numBuckets = s.readInt();table = new Entry[numBuckets];// 用于子类重写        init();// 读取entry的个数int size = s.readInt();// Read the keys and values, and put the mappings in the HashMapfor (int i=0; i<size; i++) {K key = (K) s.readObject();V value = (V) s.readObject();putForCreate(key, value);}    }    // These methods are used when serializing HashSets    int   capacity()     { return table.length; }    float loadFactor()   { return loadFactor;   }}


0 0