• HashMap


    1、开始
    public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
    继承了抽象类AbstractMap,实现了Map接口,Cloneable接口(可克隆),Serializable接口(可序列化)
    
    2、属性
    
        //默认初始化容量为16,容量必须是2的n次幂
        static final int DEFAULT_INITIAL_CAPACITY = 16;
        //最大容量为2的20次幂,再大就是Integer.MAX_VALUE
        static final int MAXIMUM_CAPACITY = 1 << 30;
        //默认加载因子为0.75
        static final float DEFAULT_LOAD_FACTOR = 0.75f;
        //Entry数组,其就是链表散列的数据结构,即数组+链表
        transient Entry<K,V>[] table;
        //已存储元素的数量
        transient int size;
        //扩容的临界值,只要存储元素的数量大于该临界值,就会自动扩容,其中threshold=capacity*load_factor
        int threshold;
        //加载因子
        final float loadFactor;
        //更改次数
        transient int modCount;
    
    3、存储数据结构Entry
    
     static class Entry<K,V> implements Map.Entry<K,V> {
            final K key;
            V value;
            Entry<K,V> next;
            int hash;
    
            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();
            }
    
            //当向HashMap添加元素时调用该方法
            void recordAccess(HashMap<K,V> m) {
            }
    
            //当从HashMap中删除元素时调用该方法
            void recordRemoval(HashMap<K,V> m) {
            }
        }
    
    4、构造器
    
        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的n次幂
            // Find a power of 2 >= initialCapacity
            int capacity = 1;
            while (capacity < initialCapacity)
                capacity <<= 1;
    
            //赋值
            //加载因子
            this.loadFactor = loadFactor;
            //扩容的临界值
            threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
            //存储元素的数组
            table = new Entry[capacity];
            //用于元素计算Hash值,定位元素在数组中的位置
            useAltHashing = sun.misc.VM.isBooted() && (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
            //初始化时的一些其他操作
            init();
        }
    
        //指定初始容量
        public HashMap(int initialCapacity) {
            this(initialCapacity, DEFAULT_LOAD_FACTOR);
        }
    
        //使用默认容量和默认加载因子
        public HashMap() {
            this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
        }
    
        //使用现有元素,和默认加载因子
        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);
        }
    
    5、添加
        
        public V put(K key, V value) {
            //当key为null时,存储在数组的第0个位置
            if (key == null)
                return putForNullKey(value);
            //计算HashCode值
            int hash = hash(key);
            //定位在数组中的位置,即确定该元素所在的链表
            int i = indexFor(hash, table.length);
            for (Entry<K,V> e = table[i]; e != null; e = e.next) {
                Object k;
                //对比hash值以及Key是否相等
                if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                    //如果存在,则将旧值替换为新值
                    V oldValue = e.value;
                    e.value = value;
                    e.recordAccess(this);
                    //返回旧值
                    return oldValue;
                }
            }
            //更改次数
            modCount++;
            //在当前数组的i位置的链表中新增一节点
            addEntry(hash, key, value, i);
            return null;
        }
    
        private V putForNullKey(V value) {
            //key为null,其必在HashMap的第0个数组中
            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++;
            //新增,hash=0,bucketIndex=0
            addEntry(0, null, value, 0);
            return null;
        }
    
        void addEntry(int hash, K key, V value, int bucketIndex) {
            //当前元素数量已经达到扩容临界点,则进行扩容
            if ((size >= threshold) && (null != table[bucketIndex])) {
                //扩容,为原来的2倍
                resize(2 * table.length);
                //重新计算当前key的hash值,
                hash = (null != key) ? hash(key) : 0;
                //以及在数组中的位置
                bucketIndex = indexFor(hash, table.length);
            }
            //为链表添加一新节点
            createEntry(hash, key, value, bucketIndex);
        }
    
        void createEntry(int hash, K key, V value, int bucketIndex) {
            //使用前插法,即新插入的元素必定在链表的头部
            Entry<K,V> e = table[bucketIndex];
            table[bucketIndex] = new Entry<>(hash, key, value, e);
            //元素数量加1
            size++;
        }
    
         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];
            boolean oldAltHashing = useAltHashing;
            useAltHashing |= sun.misc.VM.isBooted() &&
                    (newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
            //是否进行hash值重算
            boolean rehash = oldAltHashing ^ useAltHashing;
            //数组元素迁移到新数组中
            transfer(newTable, rehash);
            //最后将新数组引用赋给HashMap
            table = newTable;
            //重新计算扩容临界值
            threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
        }
    
       
        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) {
                        //是否对当前节点的hash重计算
                        e.hash = null == e.key ? 0 : hash(e.key);
                    }
                    //重新定位该元素在新数组中的位置
                    int i = indexFor(e.hash, newCapacity);
                    //将新数组中该位置的链表元素都放在该元素后面,使用的是前插法
                    e.next = newTable[i];
                    //将链表挂在新数组中
                    newTable[i] = e;
                    //继续下一个节点的迁移
                    e = next;
                }
            }
        }
    
    6、删除
    
         public V remove(Object key) {
            //获取需要删除的key对应的元素
            Entry<K,V> e = removeEntryForKey(key);
            //返回该元素上的值
            return (e == null ? null : e.value);
        }
    
        final Entry<K,V> removeEntryForKey(Object key) {
            //计算该key的hash
            int hash = (key == null) ? 0 : hash(key);
            //定位该key的在数组中的位置
            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)))) {
                    //若当前节点是所要删除的节点,即hash相等和key也相等
                    //更改次数
                    modCount++;
                    //元素数量减1
                    size--;
                    if (prev == e)
                        //当要删除的节点是链表的头结点时,则只需要将当前节点的下一个节点作为该链表的头结点,即可
                        table[i] = next;
                    else
                        //当删除的节点不是链表的头结点时,则只需要当前节点的前一个节点的下一个是当前节点的下一个节点,即可
                        prev.next = next;
                    //删除记录
                    e.recordRemoval(this);
                    //返回删除的节点
                    return e;
                }
                prev = e;
                e = next;
            }
            //返回要删除的节点
            return e;
        }
    
    7、访问和查找
        
        //根据key查找元素
        public V get(Object key) {
            if (key == null)
                //当key为null时,从数组的第0个位置查找
                return getForNullKey();
            //根据key查找
            Entry<K,V> entry = getEntry(key);
    
            return null == entry ? null : entry.getValue();
        }
    
        private V getForNullKey() {
            //从数组的第0个位置的链表头部开始查找
            for (Entry<K,V> e = table[0]; e != null; e = e.next) {
                //当存在一个key为null的节点时
                if (e.key == null)
                    //返回该节点中的值
                    return e.value;
            }
            return null;
        }
    
        //是否包含键
        public boolean containsKey(Object key) {
            return getEntry(key) != null;
        }
    
    
        final Entry<K,V> getEntry(Object key) {
            //计算该key对应的hash
            int hash = (key == null) ? 0 : hash(key);
            //定位在数组中的位置,即找到某张链表,之后从该链表的头部开始遍历
            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))))
                    //当hash相等,key也想等时,返回该节点
                    return e;
            }
            return null;
        }
    
        //是否包含值
        public boolean containsValue(Object value) {
            if (value == null)
                //当值为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() {
            //值为null
            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;
        }
    
    8、迭代器
    
        //用于HashMap的迭代器抽象类
        private abstract class HashIterator<E> implements Iterator<E> {
            Entry<K,V> next;        // next entry to return
            int expectedModCount;   // For fast-fail
            int index;              // current slot
            Entry<K,V> current;     // current entry
    
            HashIterator() {
                expectedModCount = modCount;
                if (size > 0) { // advance to first entry
                    Entry[] t = table;
                    while (index < t.length && (next = t[index++]) == null)
                        ;
                }
            }
    
            public final boolean hasNext() {
                return next != null;
            }
    
            final Entry<K,V> nextEntry() {
                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.removeEntryForKey(k);
                expectedModCount = modCount;
            }
        }
    
        //值迭代器类
        private final class ValueIterator extends HashIterator<V> {
            public V next() {
                return nextEntry().value;
            }
        }
        //键迭代器类
        private final class KeyIterator extends HashIterator<K> {
            public K next() {
                return nextEntry().getKey();
            }
        }
        //Entry迭代器类
        private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
            public Map.Entry<K,V> next() {
                return nextEntry();
            }
        }
    
        //获取键迭代器对象
        // Subclass overrides these to alter behavior of views' iterator() method
        Iterator<K> newKeyIterator()   {
            return new KeyIterator();
        }
        //获取值迭代器对象
        Iterator<V> newValueIterator()   {
            return new ValueIterator();
        }
        //获取Entry迭代器类对象
        Iterator<Map.Entry<K,V>> newEntryIterator()   {
            return new EntryIterator();
        }
    
        private transient Set<Map.Entry<K,V>> entrySet = null;
        transient volatile Set<K>        keySet = null;
        transient volatile Collection<V> values = null;
    
        //获取HashMap中的所有键对Set
        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();
            }
            //Set大小
            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();
            }
        }
    
        //获取HashMap中的所有值对Collection
        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();
            }
            //Collection大小
            public int size() {
                return size;
            }
             //是否包含
            public boolean contains(Object o) {
                return containsValue(o);
            }
            //清空
            public void clear() {
                HashMap.this.clear();
            }
        }
    
        //获取HashMap中的所有键值对Set
        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;
            }
            //Set大小
            public int size() {
                return size;
            }
            //清空
            public void clear() {
                HashMap.this.clear();
            }
        }
    
    9、清空所有元素
        public void clear() {
            modCount++;
            Entry[] tab = table;
            for (int i = 0; i < tab.length; i++)
                tab[i] = null;
            size = 0;
        }
    
    参考资料:
    http://www.cnblogs.com/tstd/p/5055286.html
    
    http://tengj.top/2016/04/15/javajh3hashmap/
  • 相关阅读:
    解决ecshop进入后台服务器出现500的问题
    Java8新特性(拉姆达表达式lambda)
    使用Optional优雅处理null
    Arrays.asList 存在的坑
    Java提供的几种线程池
    冒泡排序及优化详解
    如何让MySQL语句执行加速?
    关于https的五大误区
    127.0.0.1和0.0.0.0地址的区别
    宽带网络技术-大题重点
  • 原文地址:https://www.cnblogs.com/xiaoxian1369/p/5633763.html
Copyright © 2020-2023  润新知