HashMap

1. HashMap底层数据结构是什么?


jdk1.7

  1. 底层为 数组(Entry)+链表组成,链表为解决hash冲突而存在;
  2. 采用头插法:一般情况下,新加入的键值对被查找访问的概率更高,头插法能够提升检索效率;

jdk1.8

  1. 底层为 数组(Node)+链表+红黑树,当链表过长时会影响hashmap性能;链表检索的时间复杂度为O(n),红黑树的时间复杂度为O(logn),引入红黑树,在一定条件下链表和红黑树进行转换,提升检索性能;
  2. 采用尾插法:尾插法可以统计链表长度,判断是否大于8,而且链表过长时会转化为红黑树

2. HashMap中,关键属性有哪些?


jdk1.7

    /**
     * The default initial capacity - MUST be a power of two.
     */
     //默认初试容量,16
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    // 最大容量 1<<30
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The load factor used when none specified in constructor.
     */
    //扩容负载因子
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

jdk1.8

     /**
     * The default initial capacity - MUST be a power of two.
     */
     //默认初试容量,16
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    // 最大容量 1<<30
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The load factor used when none specified in constructor.
     */
    //扩容负载因子
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * The bin count threshold for using a tree rather than list for a
     * bin.  Bins are converted to trees when adding an element to a
     * bin with at least this many nodes. The value must be greater
     * than 2 and should be at least 8 to mesh with assumptions in
     * tree removal about conversion back to plain bins upon
     * shrinkage.
     */
    //链表转红黑树,链表长度阈值;
    static final int TREEIFY_THRESHOLD = 8;

    /**
     * The bin count threshold for untreeifying a (split) bin during a
     * resize operation. Should be less than TREEIFY_THRESHOLD, and at
     * most 6 to mesh with shrinkage detection under removal.
     */
    //红黑树转链表阈值;
    static final int UNTREEIFY_THRESHOLD = 6;

    /**
     * The smallest table capacity for which bins may be treeified.
     * (Otherwise the table is resized if too many nodes in a bin.)
     * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
     * between resizing and treeification thresholds.
     */
    //链表转红黑树,数组的长度;当链表长度>TREEIFY_THRESHOLD,且数组长度>64,则链表转红黑树,否则先扩容;
    static final int MIN_TREEIFY_CAPACITY = 64;

3.HashMap为什么线程不安全?


  1. 多线程下会形成死循环;
    jdk1.7采用的是头插法,在多线程情况下扩容,可能会导致链表的环形结构,出现死循环;jdk1.8采用的尾插法,在扩容的情况下保持链表原本的顺序,不会出现环形链表问题;
    多线程 在CAPACITY=2的HashMap中,resize之前,插入A.B.C三个数据,按照顺序排列;resize后,由于1.7按照头插法,可能导致图2的结果,最终导致A和B形成环形;
  2. 多线程的put可能导致元素丢失;
    多线程同时put操作,如果计算出来的索引位置相同,可能造成前一个key被后一个key覆盖,导致元素丢失;
  3. 多线程的put,get可能导致结果为null
    先put,然后扩容,此时其他线程get操作可能结果为空;

4.链表为什么要转红黑树,条件和原因?


  1. 在jdk1.8以前,采用数组和链表的数据结构;大量的数据在一个hash桶中时,会导致链表的长度过大,检索时间复杂度从O(1)变成O(n),降低了hashMap的性能,引入红黑树,时间复杂度为O(logn),降低检索时间,提升性能;
  2. 数组长度大于64,且链表长度大于8时,链表转为红黑树;
  3. 当链表长度小于8时,如果转红黑树,红黑树会有左旋右旋的消耗,反而降低了效率;

5.HashMap怎么解决hash冲突?


当两个对象的hashcode相等时,调用equals方法判断,相等的话则进行值覆盖,不相等则采用链表+红黑树的方式解决

6.为什么HashMap的数组大小都是2次幂?


    static int indexFor(int hashcode, int length) {
        // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
        return hashcode & (length-1);
    }

拿length=16为例
当任意hashcode与(16-1)进行与运算时,index的值与hashcode相关
15的二进制是1111;

10111011000111110100 & 1111 十进制结果 是 4;
10111011000111110110 & 1111 十进制结果 是 6;
10111011000111110101 & 1111 十进制结果 是 5;
当hashcode均匀分布时,对应到hashmap中的hash桶也是均匀分布;

7.为什么负载因子为0.75


根据泊松分布,在负载因子默认为0.75的时候,单个hash槽内元素个数为8的概率小于百万分之一,所以将7作为一个分水岭,等于7的时候不转换,大于等于8的时候才进行转换,小于等于6的时候就化为链表。

8.怎么解决HashMap线程不安全问题?


  1. Collections.synchronizedMap(Map) (全是锁)
    image
  2. HashTable (全是锁)
    image
  3. ConcurrentHashMap
posted @   andy000027  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示