HashMap

来源:互联网 发布:java api文档在哪里 编辑:程序博客网 时间:2024/06/18 13:50

1、HashMap简介

HashMap 的是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。
HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。

1.2 构造函数

HashMap()构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。HashMap(int initialCapacity)构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)。HashMap(int initialCapacity, float loadFactor)构造一个空的 HashMap具有指定的初始容量和负载因子。HashMap(Map<? extends K,? extends V> m)构造一个新的 HashMap与指定的相同的映射 Map

1.3 API

void    clear()从这张地图中删除所有的映射。Object  clone()返回此 HashMap实例的浅拷贝:键和值本身不被克隆。V   compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)尝试计算用于指定键和其当前映射的值的映射(或 null如果没有当前映射)。V   computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)如果指定的键尚未与值相关联(或映射到 null ),则尝试使用给定的映射函数计算其值,并将其输入到此映射中,除非 null 。V   computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)如果指定的密钥的值存在且非空,则尝试计算给定密钥及其当前映射值的新映射。boolean containsKey(Object key)如果此映射包含指定键的映射,则返回 trueboolean containsValue(Object value)如果此地图将一个或多个键映射到指定值,则返回 trueSet<Map.Entry<K,V>> entrySet()返回此地图中包含的映射的Set视图。void    forEach(BiConsumer<? super K,? super V> action)对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。V   get(Object key)返回到指定键所映射的值,或 null如果此映射包含该键的映射。V   getOrDefault(Object key, V defaultValue)返回到指定键所映射的值,或 defaultValue如果此映射包含该键的映射。boolean isEmpty()如果此地图不包含键值映射,则返回 trueSet<K>  keySet()返回此地图中包含的键的Set视图。V   merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)如果指定的键尚未与值相关联或与null相关联,则将其与给定的非空值相关联。V   put(K key, V value)将指定的值与此映射中的指定键相关联。void    putAll(Map<? extends K,? extends V> m)将指定地图的所有映射复制到此地图。V   putIfAbsent(K key, V value)如果指定的键尚未与某个值相关联(或映射到 null ),则将其与给定值相关联并返回 null ,否则返回当前值。V   remove(Object key)从该地图中删除指定键的映射(如果存在)。boolean remove(Object key, Object value)仅当指定的密钥当前映射到指定的值时删除该条目。V   replace(K key, V value)只有当目标映射到某个值时,才能替换指定键的条目。boolean replace(K key, V oldValue, V newValue)仅当当前映射到指定的值时,才能替换指定键的条目。void    replaceAll(BiFunction<? super K,? super V,? extends V> function)将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。int size()返回此地图中键值映射的数量。Collection<V>   values()返回此地图中包含的值的Collection视图。

1.4 继承关系

java.lang.Object   ↳     java.util.AbstractMap<K, V>         ↳     java.util.HashMap<K, V>public class HashMap<K,V>    extends AbstractMap<K,V>    implements Map<K,V>, Cloneable, Serializable { }

这里写图片描述

2、源代码

public class HashMap<K,V> extends AbstractMap<K,V>    implements Map<K,V>, Cloneable, Serializable {    //初始化容量    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16    //最大容量    static final int MAXIMUM_CAPACITY = 1 << 30;    //增长系数    static final float DEFAULT_LOAD_FACTOR = 0.75f;    //单向链表元素节点    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;        }    }    //对key进行hash    static final int hash(Object key) {        int h;        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);    }    //如果x继承Comparable且Comparable的泛型是x的类型 返回x的类型    static Class<?> comparableClassFor(Object x) {        if (x instanceof Comparable) {            Class<?> c; Type[] ts, as; Type t; ParameterizedType p;            if ((c = x.getClass()) == String.class) // bypass checks                return c;            //获取x的接口(包括接口的泛型信息)            if ((ts = c.getGenericInterfaces()) != null) {                for (int i = 0; i < ts.length; ++i) {                    if (((t = ts[i]) instanceof ParameterizedType) &&                        ((p = (ParameterizedType)t).getRawType() ==                         Comparable.class) &&                         //获取接口的泛型信息                        (as = p.getActualTypeArguments()) != null &&                        as.length == 1 && as[0] == c) // type arg is c                        return c;                }            }        }        return null;    }    //获取大于cap最小的二次幂数值    static final int tableSizeFor(int cap) {        int n = cap - 1;        n |= n >>> 1;        n |= n >>> 2;        n |= n >>> 4;        n |= n >>> 8;        n |= n >>> 16;        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;    }    //存储元素的数组,总是2的幂次倍数    transient Node<K,V>[] table;    //存放元素的集    transient Set<Map.Entry<K,V>> entrySet;    //元素的个数    transient int size;    //fail-fast    transient int modCount;    // 临界值 超过临界值,会进行扩容 临界值=总容量*填充因子    int threshold;    // 填充因子    final float 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);        this.loadFactor = loadFactor;        this.threshold = tableSizeFor(initialCapacity);    }    //带初始容量的构造    public HashMap(int initialCapacity) {        this(initialCapacity, DEFAULT_LOAD_FACTOR);    }    //默认构造    public HashMap() {        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted    }    //构造一个新的 HashMap与指定的相同的映射 Map 。    public HashMap(Map<? extends K, ? extends V> m) {        this.loadFactor = DEFAULT_LOAD_FACTOR;        putMapEntries(m, false);    }    //将m放入HashMap    final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {        int s = m.size();        if (s > 0) {            //如果table未初始化            if (table == null) { // pre-size                //元素个数/填充因子=预计的容量                float ft = ((float)s / loadFactor) + 1.0F;                int t = ((ft < (float)MAXIMUM_CAPACITY) ?                         (int)ft : MAXIMUM_CAPACITY);                //如果大于临界值,                if (t > threshold)                    //计算新的临界值                    threshold = tableSizeFor(t);            }            else if (s > threshold)                //扩容                resize();            for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {                K key = e.getKey();                V value = e.getValue();                //将m的数据放入hashmap                putVal(hash(key), key, value, false, evict);            }        }    }    //根据键获取值    public V get(Object key) {        Node<K,V> e;        return (e = getNode(hash(key), key)) == null ? null : e.value;    }    //根据键获取值    final Node<K,V> getNode(int hash, Object key) {        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;        //如果table有值,且key所在桶中有值        if ((tab = table) != null && (n = tab.length) > 0 &&            (first = tab[(n - 1) & hash]) != null) {            //如果第一个就是要找的 直接返回            if (first.hash == hash && // always check first node                ((k = first.key) == key || (key != null && key.equals(k))))                return first;            //如果桶中的节点数大于1个            if ((e = first.next) != null) {                //如果是红黑树                if (first instanceof TreeNode)                    //通过树查找                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);                //单链表的遍历、查找                do {                    if (e.hash == hash &&                        ((k = e.key) == key || (key != null && key.equals(k))))                        return e;                } while ((e = e.next) != null);            }        }        return null;    }    //存储键值对    public V put(K key, V value) {        return putVal(hash(key), key, value, false, true);    }    //放入键值对    //如果onlyIfAbsent=true 不能改变已存在的值 evict=false进入创建模式    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,                   boolean evict) {        Node<K,V>[] tab; Node<K,V> p; int n, i;        //如果table未初始化,则使用resize初始化        if ((tab = table) == null || (n = tab.length) == 0)            n = (tab = resize()).length;        //如果key的位置没有值,直接创建链表节点        //n-1为数组长度 hash为key的hash值        if ((p = tab[i = (n - 1) & hash]) == null)            tab[i] = newNode(hash, key, value, null);        //如果hash碰撞        else {            Node<K,V> e; K k;            //如果key相同,将p赋给e            if (p.hash == hash &&                ((k = p.key) == key || (key != null && key.equals(k))))                e = p;            //如果是红黑树树            else if (p instanceof TreeNode)                //调用TreeNode的putTreeVal                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);                        //如果此链表的元素大于TREEIFY_THRESHOLD 则将链表转为红黑树                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st                            treeifyBin(tab, hash);                        break;                    }                    //如果在链表中找到key break;否则继续循环                    if (e.hash == hash &&                        ((k = e.key) == key || (key != null && key.equals(k))))                        break;                    p = e;                }            }            //如果已经存在key            if (e != null) { // existing mapping for key                V oldValue = e.value;                //如果允许更改值或值为null 直接覆盖value值                if (!onlyIfAbsent || oldValue == null)                    e.value = value;                afterNodeAccess(e);                return oldValue;            }        }        ++modCount;        //如果元素个数大于临界值,则扩展        if (++size > threshold)            resize();        afterNodeInsertion(evict);        return null;    }    //扩展容量    final Node<K,V>[] resize() {        // 保存table对象        Node<K,V>[] oldTab = table;        int oldCap = (oldTab == null) ? 0 : oldTab.length;        //保存临界值        int oldThr = threshold;        int newCap, newThr = 0;        //如果之前HashMap容量大于0        if (oldCap > 0) {            //如果之前HashMap容量大于最大容量 直接返回table            if (oldCap >= MAXIMUM_CAPACITY) {                threshold = Integer.MAX_VALUE;                return oldTab;            }            //将容量*2 如果在允许范围内允许范围内,临界值也*2            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&                     oldCap >= DEFAULT_INITIAL_CAPACITY)                newThr = oldThr << 1; // double threshold        }        //为临界值赋值        else if (oldThr > 0) // initial capacity was placed in threshold            newCap = oldThr;        //初始容量和临界值        else {               // zero initial threshold signifies using defaults            newCap = DEFAULT_INITIAL_CAPACITY;            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);        }        //threshold为Cap * loadFactor        if (newThr == 0) {            float ft = (float)newCap * loadFactor;            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?                      (int)ft : Integer.MAX_VALUE);        }        threshold = newThr;        @SuppressWarnings({"rawtypes","unchecked"})        //根据新容量,创建新数组            Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];        table = newTab;        if (oldTab != null) {            //for循环为新数组赋值            for (int j = 0; j < oldCap; ++j) {                Node<K,V> e;                //如果原数组j位置不为null,保存为临时变量e                if ((e = oldTab[j]) != null) {                    //赋为null 进行释放                    oldTab[j] = null;                    //如果j位置只有一个元素 直接根据新容量找到位置并赋值                    if (e.next == null)                        newTab[e.hash & (newCap - 1)] = e;                    //如果是红黑树                     else if (e instanceof TreeNode)                        ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);                    //如果是链表 如果(e.hash & oldCap)==0 将元素放在原位置,否则偏移oldCap 不是很明白原因                    else { // preserve order                        Node<K,V> loHead = null, loTail = null;                        Node<K,V> hiHead = null, hiTail = null;                        Node<K,V> next;                        do {                            next = e.next;                            if ((e.hash & oldCap) == 0) {                                if (loTail == null)                                    loHead = e;                                else                                    loTail.next = e;                                loTail = e;                            }                            else {                                if (hiTail == null)                                    hiHead = e;                                else                                    hiTail.next = e;                                hiTail = e;                            }                        } while ((e = next) != null);                        if (loTail != null) {                            loTail.next = null;                            newTab[j] = loHead;                        }                        if (hiTail != null) {                            hiTail.next = null;                            newTab[j + oldCap] = hiHead;                        }                    }                }            }        }        return newTab;    }    //链表转为树结构    final void treeifyBin(Node<K,V>[] tab, int hash) {        int n, index; Node<K,V> e;        //如果容量太小 直接扩展        if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)            resize();        else if ((e = tab[index = (n - 1) & hash]) != null) {            TreeNode<K,V> hd = null, tl = null;            do {                //将Node转换为TreeNode                TreeNode<K,V> p = replacementTreeNode(e, null);                if (tl == null)                    hd = p;                else {                    p.prev = tl;                    tl.next = p;                }                tl = p;            } while ((e = e.next) != null);            if ((tab[index] = hd) != null)                //转换为红黑树结构                hd.treeify(tab);        }    }    //移除    public V remove(Object key) {        Node<K,V> e;        return (e = removeNode(hash(key), key, null, false, true)) == null ?            null : e.value;    }    //移除节点的具体操作    final Node<K,V> removeNode(int hash, Object key, Object value,                               boolean matchValue, boolean movable) {        Node<K,V>[] tab; Node<K,V> p; int n, index;        //找到key对应的节点        if ((tab = table) != null && (n = tab.length) > 0 &&            (p = tab[index = (n - 1) & hash]) != null) {            Node<K,V> node = null, e; K k; V v;            if (p.hash == hash &&                ((k = p.key) == key || (key != null && key.equals(k))))                node = p;            else if ((e = p.next) != null) {                if (p instanceof TreeNode)                    node = ((TreeNode<K,V>)p).getTreeNode(hash, key);                else {                    do {                        if (e.hash == hash &&                            ((k = e.key) == key ||                             (key != null && key.equals(k)))) {                            node = e;                            break;                        }                        p = e;                    } while ((e = e.next) != null);                }            }            //移除            if (node != null && (!matchValue || (v = node.value) == value ||                                 (value != null && value.equals(v)))) {                if (node instanceof TreeNode)                    ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);                else if (node == p)                    tab[index] = node.next;                else                    p.next = node.next;                ++modCount;                --size;                afterNodeRemoval(node);                return node;            }        }        return null;    }    //返回“key的集合”,实际上返回一个“KeySet对象”    public Set<Map.Entry<K,V>> entrySet() {        Set<Map.Entry<K,V>> es;        return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;    }    //返回“key的集合”,实际上返回一个“KeySet对象”    final class EntrySet extends AbstractSet<Map.Entry<K,V>> {        public final int size()                 { return size; }        public final void clear()               { HashMap.this.clear(); }        public final Iterator<Map.Entry<K,V>> iterator() {            return new EntryIterator();        }        public final boolean contains(Object o) {            if (!(o instanceof Map.Entry))                return false;            Map.Entry<?,?> e = (Map.Entry<?,?>) o;            Object key = e.getKey();            Node<K,V> candidate = getNode(hash(key), key);            return candidate != null && candidate.equals(e);        }        public final boolean remove(Object o) {            if (o instanceof Map.Entry) {                Map.Entry<?,?> e = (Map.Entry<?,?>) o;                Object key = e.getKey();                Object value = e.getValue();                return removeNode(hash(key), key, value, true, true) != null;            }            return false;        }        public final Spliterator<Map.Entry<K,V>> spliterator() {            return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);        }        public final void forEach(Consumer<? super Map.Entry<K,V>> action) {            Node<K,V>[] tab;            if (action == null)                throw new NullPointerException();            if (size > 0 && (tab = table) != null) {                int mc = modCount;                for (int i = 0; i < tab.length; ++i) {                    for (Node<K,V> e = tab[i]; e != null; e = e.next)                        action.accept(e);                }                if (modCount != mc)                    throw new ConcurrentModificationException();            }        }    }}

TreeNode 红黑树部分
参照:http://blog.csdn.net/with_dream/article/details/77012542

    static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {        TreeNode<K,V> parent;  // red-black tree links        TreeNode<K,V> left;        TreeNode<K,V> right;        TreeNode<K,V> prev;    // needed to unlink next upon deletion        boolean red;        TreeNode(int hash, K key, V val, Node<K,V> next) {            super(hash, key, val, next);        }        /**         * Returns root of tree containing this node.         */         //只有根元素的父节点为null        final TreeNode<K,V> root() {            for (TreeNode<K,V> r = this, p;;) {                if ((p = r.parent) == null)                    return r;                r = p;            }        }        /**         * Ensures that the given root is the first node of its bin.         */        static <K,V> void moveRootToFront(Node<K,V>[] tab, TreeNode<K,V> root) {            int n;            if (root != null && tab != null && (n = tab.length) > 0) {                int index = (n - 1) & root.hash;                TreeNode<K,V> first = (TreeNode<K,V>)tab[index];                if (root != first) {                    Node<K,V> rn;                    tab[index] = root;                    TreeNode<K,V> rp = root.prev;                    if ((rn = root.next) != null)                        ((TreeNode<K,V>)rn).prev = rp;                    if (rp != null)                        rp.next = rn;                    if (first != null)                        first.prev = root;                    root.next = first;                    root.prev = null;                }                assert checkInvariants(root);            }        }        /**         * Finds the node starting at root p with the given hash and key.         * The kc argument caches comparableClassFor(key) upon first use         * comparing keys.         */        final TreeNode<K,V> find(int h, Object k, Class<?> kc) {            TreeNode<K,V> p = this;            do {                int ph, dir; K pk;                TreeNode<K,V> pl = p.left, pr = p.right, q;                if ((ph = p.hash) > h)                    p = pl;                else if (ph < h)                    p = pr;                else if ((pk = p.key) == k || (k != null && k.equals(pk)))                    return p;                else if (pl == null)                    p = pr;                else if (pr == null)                    p = pl;                else if ((kc != null ||                          (kc = comparableClassFor(k)) != null) &&                         (dir = compareComparables(kc, k, pk)) != 0)                    p = (dir < 0) ? pl : pr;                else if ((q = pr.find(h, k, kc)) != null)                    return q;                else                    p = pl;            } while (p != null);            return null;        }        /**         * Calls find for root node.         */        final TreeNode<K,V> getTreeNode(int h, Object k) {            return ((parent != null) ? root() : this).find(h, k, null);        }        /**         * Tie-breaking utility for ordering insertions when equal         * hashCodes and non-comparable. We don't require a total         * order, just a consistent insertion rule to maintain         * equivalence across rebalancings. Tie-breaking further than         * necessary simplifies testing a bit.         */        static int tieBreakOrder(Object a, Object b) {            int d;            if (a == null || b == null ||                (d = a.getClass().getName().                 compareTo(b.getClass().getName())) == 0)                d = (System.identityHashCode(a) <= System.identityHashCode(b) ?                     -1 : 1);            return d;        }        /**         * Forms tree of the nodes linked from this node.         * @return root of tree         */        //链表转红黑树        final void treeify(Node<K,V>[] tab) {            TreeNode<K,V> root = null;            //this为链表首元素            //循环整个链表            for (TreeNode<K,V> x = this, next; x != null; x = next) {                next = (TreeNode<K,V>)x.next;                x.left = x.right = null;                //将第一个元素赋为root                if (root == null) {                    x.parent = null;                    x.red = false;                    root = x;                }                else {                    K k = x.key;                    int h = x.hash;                    Class<?> kc = null;                    //在红黑树中遍历                    for (TreeNode<K,V> p = root;;) {                        int dir, ph;                        K pk = p.key;                        //根据hash判断大小                        if ((ph = p.hash) > h)                            dir = -1;                        else if (ph < h)                            dir = 1;                        else if ((kc == null &&                                  (kc = comparableClassFor(k)) == null) ||                                 (dir = compareComparables(kc, k, pk)) == 0)                            dir = tieBreakOrder(k, pk);                        TreeNode<K,V> xp = p;                        //插入叶子位置                        if ((p = (dir <= 0) ? p.left : p.right) == null) {                            x.parent = xp;                            if (dir <= 0)                                xp.left = x;                            else                                xp.right = x;                            //修正红黑树                            root = balanceInsertion(root, x);                            break;                        }                    }                }            }            moveRootToFront(tab, root);        }        /**         * Returns a list of non-TreeNodes replacing those linked from         * this node.         */        //TreeNode转换为Node        final Node<K,V> untreeify(HashMap<K,V> map) {            Node<K,V> hd = null, tl = null;            for (Node<K,V> q = this; q != null; q = q.next) {                Node<K,V> p = map.replacementNode(q, null);                if (tl == null)                    hd = p;                else                    tl.next = p;                tl = p;            }            return hd;        }        /**         * Tree version of putVal.         */        //向红黑树插入元素        final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab,                                       int h, K k, V v) {            Class<?> kc = null;            boolean searched = false;            TreeNode<K,V> root = (parent != null) ? root() : this;            //遍历            for (TreeNode<K,V> p = root;;) {                int dir, ph; K pk;                //比较hash值                if ((ph = p.hash) > h)                    dir = -1;                else if (ph < h)                    dir = 1;                //如果键相同 直接返回元素                else if ((pk = p.key) == k || (k != null && k.equals(pk)))                    return p;                //没看懂                else if ((kc == null &&                          (kc = comparableClassFor(k)) == null) ||                         (dir = compareComparables(kc, k, pk)) == 0) {                    if (!searched) {                        TreeNode<K,V> q, ch;                        searched = true;                        if (((ch = p.left) != null &&                             (q = ch.find(h, k, kc)) != null) ||                            ((ch = p.right) != null &&                             (q = ch.find(h, k, kc)) != null))                            return q;                    }                    dir = tieBreakOrder(k, pk);                }                TreeNode<K,V> xp = p;                if ((p = (dir <= 0) ? p.left : p.right) == null) {                    Node<K,V> xpn = xp.next;                    //新建TreeNode                    TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn);                    //追加                    if (dir <= 0)                        xp.left = x;                    else                        xp.right = x;                    xp.next = x;                    x.parent = x.prev = xp;                    if (xpn != null)                        ((TreeNode<K,V>)xpn).prev = x;                    //调用balanceInsertion插入,并将root放入桶中                    moveRootToFront(tab, balanceInsertion(root, x));                    return null;                }            }        }        /**         * Removes the given node, that must be present before this call.         * This is messier than typical red-black deletion code because we         * cannot swap the contents of an interior node with a leaf         * successor that is pinned by "next" pointers that are accessible         * independently during traversal. So instead we swap the tree         * linkages. If the current tree appears to have too few nodes,         * the bin is converted back to a plain bin. (The test triggers         * somewhere between 2 and 6 nodes, depending on tree structure).         */        final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab,                                  boolean movable) {            int n;            if (tab == null || (n = tab.length) == 0)                return;            int index = (n - 1) & hash;            TreeNode<K,V> first = (TreeNode<K,V>)tab[index], root = first, rl;            TreeNode<K,V> succ = (TreeNode<K,V>)next, pred = prev;            if (pred == null)                tab[index] = first = succ;            else                pred.next = succ;            if (succ != null)                succ.prev = pred;            if (first == null)                return;            if (root.parent != null)                root = root.root();            if (root == null || root.right == null ||                (rl = root.left) == null || rl.left == null) {                tab[index] = first.untreeify(map);  // too small                return;            }            TreeNode<K,V> p = this, pl = left, pr = right, replacement;            if (pl != null && pr != null) {                TreeNode<K,V> s = pr, sl;                while ((sl = s.left) != null) // find successor                    s = sl;                boolean c = s.red; s.red = p.red; p.red = c; // swap colors                TreeNode<K,V> sr = s.right;                TreeNode<K,V> pp = p.parent;                if (s == pr) { // p was s's direct parent                    p.parent = s;                    s.right = p;                }                else {                    TreeNode<K,V> sp = s.parent;                    if ((p.parent = sp) != null) {                        if (s == sp.left)                            sp.left = p;                        else                            sp.right = p;                    }                    if ((s.right = pr) != null)                        pr.parent = s;                }                p.left = null;                if ((p.right = sr) != null)                    sr.parent = p;                if ((s.left = pl) != null)                    pl.parent = s;                if ((s.parent = pp) == null)                    root = s;                else if (p == pp.left)                    pp.left = s;                else                    pp.right = s;                if (sr != null)                    replacement = sr;                else                    replacement = p;            }            else if (pl != null)                replacement = pl;            else if (pr != null)                replacement = pr;            else                replacement = p;            if (replacement != p) {                TreeNode<K,V> pp = replacement.parent = p.parent;                if (pp == null)                    root = replacement;                else if (p == pp.left)                    pp.left = replacement;                else                    pp.right = replacement;                p.left = p.right = p.parent = null;            }            TreeNode<K,V> r = p.red ? root : balanceDeletion(root, replacement);            if (replacement == p) {  // detach                TreeNode<K,V> pp = p.parent;                p.parent = null;                if (pp != null) {                    if (p == pp.left)                        pp.left = null;                    else if (p == pp.right)                        pp.right = null;                }            }            if (movable)                moveRootToFront(tab, r);        }        /**         * Splits nodes in a tree bin into lower and upper tree bins,         * or untreeifies if now too small. Called only from resize;         * see above discussion about split bits and indices.         *         * @param map the map         * @param tab the table for recording bin heads         * @param index the index of the table being split         * @param bit the bit of hash to split on         */        final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) {            TreeNode<K,V> b = this;            // Relink into lo and hi lists, preserving order            TreeNode<K,V> loHead = null, loTail = null;            TreeNode<K,V> hiHead = null, hiTail = null;            int lc = 0, hc = 0;            for (TreeNode<K,V> e = b, next; e != null; e = next) {                next = (TreeNode<K,V>)e.next;                e.next = null;                if ((e.hash & bit) == 0) {                    if ((e.prev = loTail) == null)                        loHead = e;                    else                        loTail.next = e;                    loTail = e;                    ++lc;                }                else {                    if ((e.prev = hiTail) == null)                        hiHead = e;                    else                        hiTail.next = e;                    hiTail = e;                    ++hc;                }            }            if (loHead != null) {                if (lc <= UNTREEIFY_THRESHOLD)                    tab[index] = loHead.untreeify(map);                else {                    tab[index] = loHead;                    if (hiHead != null) // (else is already treeified)                        loHead.treeify(tab);                }            }            if (hiHead != null) {                if (hc <= UNTREEIFY_THRESHOLD)                    tab[index + bit] = hiHead.untreeify(map);                else {                    tab[index + bit] = hiHead;                    if (loHead != null)                        hiHead.treeify(tab);                }            }        }        /* ------------------------------------------------------------ */        // Red-black tree methods, all adapted from CLR        //左旋转        static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,                                              TreeNode<K,V> p) {            TreeNode<K,V> r, pp, rl;            if (p != null && (r = p.right) != null) {                if ((rl = p.right = r.left) != null)                    rl.parent = p;                if ((pp = r.parent = p.parent) == null)                    (root = r).red = false;                else if (pp.left == p)                    pp.left = r;                else                    pp.right = r;                r.left = p;                p.parent = r;            }            return root;        }        //右旋转        static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root,                                               TreeNode<K,V> p) {            TreeNode<K,V> l, pp, lr;            if (p != null && (l = p.left) != null) {                if ((lr = p.left = l.right) != null)                    lr.parent = p;                if ((pp = l.parent = p.parent) == null)                    (root = l).red = false;                else if (pp.right == p)                    pp.right = l;                else                    pp.left = l;                l.right = p;                p.parent = l;            }            return root;        }        //调整红黑树        static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,                                                    TreeNode<K,V> x) {            x.red = true;            for (TreeNode<K,V> xp, xpp, xppl, xppr;;) {                //如果只有一个元素 直接返回                if ((xp = x.parent) == null) {                    x.red = false;                    return x;                }                //如果                else if (!xp.red || (xpp = xp.parent) == null)                    return root;                //一、若“父节点”是“祖父节点的左孩子”                if (xp == (xppl = xpp.left)) {                    //如果叔叔节点是红色  则父节点、叔叔节点都为黑,祖父节点为红                    if ((xppr = xpp.right) != null && xppr.red) {                        xppr.red = false;                        xp.red = false;                        xpp.red = true;                        x = xpp;                    }                    else {                        //如果当前节点为右节点 则左转换                        if (x == xp.right) {                            root = rotateLeft(root, x = xp);                            xpp = (xp = x.parent) == null ? null : xp.parent;                        }                        //右旋转                        if (xp != null) {                            xp.red = false;                            if (xpp != null) {                                xpp.red = true;                                root = rotateRight(root, xpp);                            }                        }                    }                }                else {                    if (xppl != null && xppl.red) {                        xppl.red = false;                        xp.red = false;                        xpp.red = true;                        x = xpp;                    }                    else {                        if (x == xp.left) {                            root = rotateRight(root, x = xp);                            xpp = (xp = x.parent) == null ? null : xp.parent;                        }                        if (xp != null) {                            xp.red = false;                            if (xpp != null) {                                xpp.red = true;                                root = rotateLeft(root, xpp);                            }                        }                    }                }            }        }        //红黑树的删除操作        static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,                                                   TreeNode<K,V> x) {            for (TreeNode<K,V> xp, xpl, xpr;;)  {                if (x == null || x == root)                    return root;                else if ((xp = x.parent) == null) {                    x.red = false;                    return x;                }                else if (x.red) {                    x.red = false;                    return root;                }                else if ((xpl = xp.left) == x) {                    if ((xpr = xp.right) != null && xpr.red) {                        xpr.red = false;                        xp.red = true;                        root = rotateLeft(root, xp);                        xpr = (xp = x.parent) == null ? null : xp.right;                    }                    if (xpr == null)                        x = xp;                    else {                        TreeNode<K,V> sl = xpr.left, sr = xpr.right;                        if ((sr == null || !sr.red) &&                            (sl == null || !sl.red)) {                            xpr.red = true;                            x = xp;                        }                        else {                            if (sr == null || !sr.red) {                                if (sl != null)                                    sl.red = false;                                xpr.red = true;                                root = rotateRight(root, xpr);                                xpr = (xp = x.parent) == null ?                                    null : xp.right;                            }                            if (xpr != null) {                                xpr.red = (xp == null) ? false : xp.red;                                if ((sr = xpr.right) != null)                                    sr.red = false;                            }                            if (xp != null) {                                xp.red = false;                                root = rotateLeft(root, xp);                            }                            x = root;                        }                    }                }                else { // symmetric                    if (xpl != null && xpl.red) {                        xpl.red = false;                        xp.red = true;                        root = rotateRight(root, xp);                        xpl = (xp = x.parent) == null ? null : xp.left;                    }                    if (xpl == null)                        x = xp;                    else {                        TreeNode<K,V> sl = xpl.left, sr = xpl.right;                        if ((sl == null || !sl.red) &&                            (sr == null || !sr.red)) {                            xpl.red = true;                            x = xp;                        }                        else {                            if (sl == null || !sl.red) {                                if (sr != null)                                    sr.red = false;                                xpl.red = true;                                root = rotateLeft(root, xpl);                                xpl = (xp = x.parent) == null ?                                    null : xp.left;                            }                            if (xpl != null) {                                xpl.red = (xp == null) ? false : xp.red;                                if ((sl = xpl.left) != null)                                    sl.red = false;                            }                            if (xp != null) {                                xp.red = false;                                root = rotateRight(root, xp);                            }                            x = root;                        }                    }                }            }        }        /**         * Recursive invariant check         */        static <K,V> boolean checkInvariants(TreeNode<K,V> t) {            TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,                tb = t.prev, tn = (TreeNode<K,V>)t.next;            if (tb != null && tb.next != t)                return false;            if (tn != null && tn.prev != t)                return false;            if (tp != null && t != tp.left && t != tp.right)                return false;            if (tl != null && (tl.parent != t || tl.hash > t.hash))                return false;            if (tr != null && (tr.parent != t || tr.hash < t.hash))                return false;            if (t.red && tl != null && tl.red && tr != null && tr.red)                return false;            if (tl != null && !checkInvariants(tl))                return false;            if (tr != null && !checkInvariants(tr))                return false;            return true;        }    }

2.2 主要方法

2.2.1 put
这里写图片描述

2.3 遍历

    public static void main(String[] args) {        Map<String, String> map = new HashMap<String, String>();        //使用EntrySet遍历   //如果需要遍历key和set 推荐使用        for (Map.Entry<String, String> entry : map.entrySet()) {            entry.getKey();            entry.getValue();        }        //迭代器        Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();        while (iterator.hasNext()) {            Map.Entry<String, String> entry = iterator.next();            entry.getKey();            entry.getValue();        }        //keySet的到key的集 再foreach      //如果只遍历key 推荐使用        for (String key : map.keySet()) {            map.get(key);        }        //        Set<Map.Entry<String, String>> entrySet = map.entrySet();        for (Map.Entry<String, String> entry : entrySet) {            entry.getKey();            entry.getValue();        }    }

3、总结

3.1 HashMap的数据结构为散列表,如果有碰撞,会将碰撞的元素构建为单链表的形式。如果链表长度大于8且容量大于64,会将链表结构转换为红黑树结构。
如果红黑树的个数减小到小于6,则会将红黑树再次转换为链表结构
1.8才有红黑树,之前只是单链表

3.2 HashMap的扩容每次都是原容量*2(在resize中),扩容之后需要重新散列计算位置并赋值,对链表或树进行调整,很消耗性能。所以最好选择一个合适大小的容量

3.3 HashMap的table数组下标为int类型,所以最大可以盛放2^32个数据。但是内存无法盛放如此多的数据,所以计算桶的位置时使用(n - 1) & hash,n为数组的总长度。

n总是2的次方(resize方法中),所以n-1使低n-1位全为1。与上hash可以抹去hash的高位,保证(n - 1) & hash的位置总是落在0~n的范围内

hash值只使用低位,增加了碰撞的几率,所以使用扰动函数即hash方法,使hash值均匀分布

    static final int hash(Object key) {        int h;        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);    }

这里写图片描述
参考:https://www.zhihu.com/question/20733617

3.4 HashMap的扩容是根据threshold,threshold=容量*填充因子。当元素个数大于threshold,就会进行扩充。

3.5 HashMap不是线程安全的,如果在多线程下使用需要加锁或者使用线程安全的Map。
https://coolshell.cn/articles/9606.html#more-9606

参考:
http://www.cnblogs.com/skywang12345/p/3310835.html