首页 > 编程语言 > 详细

[Java基础]——哈希表详解

时间:2021-07-01 00:26:27      阅读:23      评论:0      收藏:0      [点我收藏+]

  此博客主要记录哈希表的具体原理,及常见的面试题目。

 

一、Map接口继承树

        技术分享图片

 

   /-- Map: 双列数据,存储key-value 对的数据

    /-- HashMap : 作为Map的主要实现类;线程不安全,效率高;存储null 的key 和value(1.2出现)

        /-- LinkedHashMap: 保证在遍历map元素时,可以按照添加的顺序实现遍历 (1.4出现)

                (原因: 在原有的HashMap底层结构的基础上,添加了一对指针,指向前一个和后一个元素。对于频繁遍历操作,此类执行效率高)

    /-- TreeMap:  保证按照添加的key - value 对进行排序,实现排序遍历。此时考虑key 的自然排序(1.2出现)

                 底层实现红黑树

    /-- Hashtable : 作为古老的实现类; 线程安全,效率低;不能存储null 的key 和value (1.0出现)

        /-- Properties:  常用来处理配置文件。 key和value 都是String类型

  

 

  HashMap的底层: 数组 + 链表 (jdk7 之前)

                                      数组 + 链表 + 红黑树 (jdk 8)

 

 

二、HashMap 底层实现原理

  map结构的理解:

  Map中的key : 无序、不可重复,使用Set 储存所有的key    ---> key 所在的类要重写 equals() 和 hashCode() (HashMap 为例)

  Map中的value: 无序、可重复, 使用Collection存储所有的value   ---> value 所在的类要重写equals()

  Map中的entry : 无序、不可重复, 使用 Set 存储所有的entry 

 

  底层实现原理? 以jdk 7 为例:

  HashMap map = new HashMap();

  在实例化以后, 底层创建了长度为16的一维数组 Entry[ ] table。 

  map. put(key1, value1);

  首先,调用key1 所在类的hashCode() 计算key1 的哈希值, 此哈希值经过某种算法(可以想象为取模,源码上和(length - 1)进行 “与” 运算)以后,得到在Entry 数组中的存放位置。

  如果此位置上的数据为空,则此时的entry(key1- value1) 添加成功。

  如果此位置上的数据不为空,意味着此位置上存在一个或者多个数据(以链表的方式存在),比较key1和已经存在的一个或者多个数据的哈希值。

    如果key1的哈希值与已经存在的哈希值都不相同,此时添加成功。

    如果哈希值重复,继续比较equals()。返回false则添加成功;返回true,则更新相同key 值的 value。

  在不断添加的过程中,会涉及到扩容的问题,默认的扩容方式:扩容为原来的两倍,并将原有的数据复制过来。

  吞吐临界值(或者叫阈值、threshold) 是负载因子(或者叫填充比)乘以哈希表底层数组长度。

  (当size的长度大于或等于阈值(一般是0.75),并且插入的位置不是null (要插入进链表),就要扩容,扩容为原来的两倍)

  技术分享图片

 

 

  jdk 8 相较于jdk 7在底层实现方面的不同:

  1. new HashMap() : 底层没有创建一个长度为16的数组

  2. jdk 8 底层数组是: Node[ ] , 而非 Entry [ ] 

  3. 首次调用put ( ) , 方法时,底层调用长度为16 的数组  

  4. jdk 7底层结构只有: 数组+ 链表, jdk 8 中底层结构: 数组 + 链表+ 红黑树。

 

  当数组的某一个索引位置上的元素以链表的形式存在的数据个数 > 8 且当前数组的长度 > 64时,此时此索引上位置的所有数据改为使用红黑树存储。

  DEFAULT_INITIAL_CAPACITY : HashMap 的默认容量, 16

  EDFAULT_LOAD_FACTOR : HashMap 的默认加载因子, 0.75

  threshold : 扩容临界值, = 容量 * 填充因子 , 16 * 0.75 = 12

  TREEIFY_THRESHOLD : Bucket 中链表长度大于该默认值,转化为红黑树, 8

  MIN_TREEEIFY_CAPACITY : 桶中的Node 被树化时最小的hash 表容量, 64

 

三、红黑树

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

面试题:

1. HashMap 的底层实现原理 ?

2. HashMap 和HashTable 的区别 ?

3. CurrentHashMap 与 Hashtable 的异同?

 

[Java基础]——哈希表详解

原文:https://www.cnblogs.com/nobita/p/14956413.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!