zoukankan      html  css  js  c++  java
  • hashMap的源码实现

    1、初步认识hashMap

    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>(5);
        map.put("中国", 1);
        map.put("美国", 2);
        map.put("俄罗斯", 3);
        map.put("英国", 4);
        map.put("法国", 5);
        for(Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }

    debug模式,从数据结构上认知HashMap:

    JDK8中HashMap的数据结构源码:

     static class Node<K,V> implements Map.Entry<K,V> {
            final int hash;
            final K key;
            V value;
            Node<K,V> next;
    
            Node(int hash, K key, V value, Node<K,V> next) {
                this.hash = hash;
                this.key = key;
                this.value = value;
                this.next = next;
            }
    
            public final K getKey()        { return key; }
            public final V getValue()      { return value; }
            public final String toString() { return key + "=" + value; }
    
            public final int hashCode() {
                return Objects.hashCode(key) ^ Objects.hashCode(value);
            }
    
            public final V setValue(V newValue) {
                V oldValue = value;
                value = newValue;
                return oldValue;
            }
    
            public final boolean equals(Object o) {
                if (o == this)
                    return true;
                if (o instanceof Map.Entry) {
                    Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                    if (Objects.equals(key, e.getKey()) &&
                        Objects.equals(value, e.getValue()))
                        return true;
                }
                return false;
            }
        }

    2、HashMap的两个重要参数

    /**
    * The default initial capacity - MUST be a power of two.
    * table的默认初始容量
    */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
    /** * The load factor used when none specified in constructor.(负载因子) */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
    • capacity 就是初始化HashMap时的数组容量,load factor 指负载因子;
    • 当我们对迭代性能要求比较高时,不能把capacity设置的太大;同时load factor不要超过0.75,否则会明显增加冲突几率,降低HashMap性能;
    •  hashMap中元素数量( put 的元素个数) > (负载因子 * 容量) 时,就需要扩容为原来的2倍

    3、HashMap的put(Key k,Value v)的原理

    数据存储的步骤

    1.  当在第一次put时,先对table初始化,通过hash计算得到存放位置table[i],存放。
    2.  当再次put时,同样经过hash计算得到位置,则采用链表法解决冲突存放在相同位置的next区域
    3.  在JDK8中设置了链表的默认阈值为8,如果超过这个值,则进行树化。
    4.  如果节点已经存在就替换old value(保证key的唯一性)。
    5.  如果bucket满了(超过load factor*current capacity),就要resize,变为原来2倍。

    面试题:解释HashMap的原理,数据量增大时,数据结构是什么样的?
           在数据量小的时候,HashMap是按照链表的模式存储的。当数据量变大之后,为了进行快速的查找,会将这个链表变成红黑树(均衡二叉树),用hash码作为数据的定位来进行保存。

    /**
         * Associates the specified value with the specified key in this map.
         * If the map previously contained a mapping for the key, the old
         * value is replaced.
         *
         * @param key key with which the specified value is to be associated
         * @param value value to be associated with the specified key
         * @return the previous value associated with <tt>key</tt>, or
         *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
         *         (A <tt>null</tt> return can also indicate that the map
         *         previously associated <tt>null</tt> with <tt>key</tt>.)
         */
        public V put(K key, V value) {
            return putVal(hash(key), key, value, false, true);
        }
    
        /**
         * Implements Map.put and related methods
         *
         * @param hash hash for key
         * @param key the key
         * @param value the value to put
         * @param onlyIfAbsent if true, don't change existing value
         * @param evict if false, the table is in creation mode.
         * @return previous value, or null if none
         */
        final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                       boolean evict) {
            Node<K,V>[] tab; Node<K,V> p; int n, i;
            if ((tab = table) == null || (n = tab.length) == 0)
                n = (tab = resize()).length;
            if ((p = tab[i = (n - 1) & hash]) == null)
                tab[i] = newNode(hash, key, value, null);
            else {
                Node<K,V> e; K k;
                if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k))))
                    e = p;
                else if (p instanceof TreeNode)
                    e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
                else {
                    for (int binCount = 0; ; ++binCount) {
                        if ((e = p.next) == null) {
                            p.next = newNode(hash, key, value, null);
                            if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                                treeifyBin(tab, hash);
                            break;
                        }
                        if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k))))
                            break;
                        p = e;
                    }
                }
                if (e != null) { // existing mapping for key
                    V oldValue = e.value;
                    if (!onlyIfAbsent || oldValue == null)
                        e.value = value;
                    afterNodeAccess(e);
                    return oldValue;
                }
            }
            ++modCount;
            if (++size > threshold)
                resize();
            afterNodeInsertion(evict);
            return null;
        }
  • 相关阅读:
    Hadoop集群(三) Hbase搭建
    Hadoop集群(二) HDFS搭建
    Hadoop集群(一) Zookeeper搭建
    Redis Cluster 添加/删除 完整折腾步骤
    Redis Cluster在线迁移
    Hadoop分布式HA的安装部署
    Describe the difference between repeater, bridge and router.
    what is the “handover” and "soft handover" in mobile communication system?
    The main roles of LTE eNodeB.
    The architecture of LTE network.
  • 原文地址:https://www.cnblogs.com/luao/p/10931769.html
Copyright © 2011-2022 走看看