Loading

【Java】HashMap的实现原理

一、简介

HashMap是基于Map接口的具体实现类,可以存储null键和null值。

相比于HashtableHashMap是线程不安全的,没有同步操作,效率高。

二、键唯一性

HashMap中的泛型是<K,V>格式的,在具体的实现中,HashMap是可以保证键的唯一性的,但是存在特殊情况。

  • 如果是基本数据类型或者内置数据类型的包装类,例如:IntegerString等,可以保证键的唯一性。如果添加相同的键的数据多次,则会按照添加顺序覆盖最先添加的数据。
  • 如果是引用数据,如Object类,则不能保证键的唯一性,即不能保证去重效果。想要保证去重效果,则需要在定义类的时候重写hashCode()方法和equals()方法

HashSet保证元素唯一性原理

三、结构

在jdk 8中,HashMap是由数组+链表+红黑树共同实现的。

HashSet(HashMap)是如何存储存储数据的

四、扩容

  • 扩容长度:默认数组的长度是16,并且发生扩容的时候,长度都为之前的2倍。也就是说,长度只可能为16、32、64……
  • 加载因子:扩容发生的阈值,因为扩容是在容量用完之前就需要进行的。如果等到用完之后需要添加大量数据,这个时候还没来得及扩容就会发生容量不够用的情况。
    • 目前的阈值参数为0.75。如果按照初始值容量计算,当占用容量空间达到16*0.75=12时,就会发生扩容,扩容之后的容量变为16*2=32;后续情况依此类推。
  • 转换为红黑树:当哈希表上同一位置上的数据过多,即单一Node上的数据量过多,该Node上的数据默认会使用链表的结构进行排列,数据过多就会造成效率低下,JDK 8中对此情况做了优化:数据量到一定程度的时候,将链表形式的数据转换为红黑树的结构。
    • 转换条件:如果一条链表中元素的个数达到TREEIFY_THRESHOLD(默认是8),并且table的长度大于 MIN_TREEIFY_CAPACITY(默认是64),就会将链表转为红黑树来提高效率(JDK 8)。
    • 如果一条链表中元素的个数达到TREEIFY_THRESHOLD(默认是8),并且table的长度小于 MIN_TREEIFY_CAPACITY(默认是64),那么链表并不会转为红黑树,而是将数组扩大至原来的2倍(并且是每添加一 次就扩大2倍),直到数组长度达到64(此时链表就可以转为红黑树了),也就达到了效率最高。
      • 前者满足,后者不满足:则链表中每添加一个数据,数组长度扩大为原来的两倍,直至table的长度达到 MIN_TREEIFY_CAPACITY(默认是64),转换为红黑树。
      • 前者不满足,后者满足:链表中数据长度不足够转换为红黑树,两者效率差距不大,直至链表中数据增加至TREEIFY_THRESHOLD(默认是8),转换为红黑树。

五、TreeMap

TreeMap是基于红黑树(Red-Black tree)的 NavigableMap 的实现类。

该映射根据其键的自然顺序进行排序, 或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。

实现类中不包含同步代码块,线程非安全,效率高。

posted @ 2021-06-28 20:41  雨下一整晚Real  阅读(9)  评论(0编辑  收藏  举报  来源