当前位置:   article > 正文

简述哈希表_哈希表详细解释

哈希表详细解释

目录

一 、什么是哈希表

二、哈希表的结构

三、哈希表的新增

四、哈希表的扩容

                哈希表的底层数组会在一下两种情况下扩容:

                什么情况下链表转红黑树?


一 、什么是哈希表

哈希表的英文叫 Hash Table,也可以称为散列表或者 Hash 表。哈希表用的是数组支持按照下标随机访问数据的特性,所以哈希表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表哈希表存储的是由键(key)和值(value)组成的数据。

二、哈希表的结构

JDK1.8以前哈希表是由数组+链表组成

JDK1.8开始哈希表是由数组+链表+红黑树组成

加入红黑树的好处:

链表的特点是增删快,查询慢。所以链表越长就会导致查询越慢,而红黑树恰好解决这一问题。

数组类型:哈希表的数组类型是java.util包下的HashMap$Node类型的数组

  1. /**
  2. * Basic hash bin node, used for most entries. (See below for
  3. * TreeNode subclass, and in LinkedHashMap for its Entry subclass.)
  4. */
  5. static class Node<K,V> implements Map.Entry<K,V> {
  6. final int hash;
  7. final K key;
  8. V value;
  9. Node<K,V> next;
  10. Node(int hash, K key, V value, Node<K,V> next) {
  11. this.hash = hash;
  12. this.key = key;
  13. this.value = value;
  14. this.next = next;
  15. }

数组长度:

未定义数组长度会创建一个初始化长度为16的数组

如果定义了数组长度则数组是最接近二的n次方。例:定义长度为100的数组实际长度为128=2的6次方。

三、哈希表的新增

  1. 计算新增元素的哈希值。
  2. 用hash%数组长度,计算索引值。
  3. 判断该索引值位置是否为空;
    1. 如果该索引值为空直接新增;
    2. 如果不为空,则判断该索引值位置的元素是否重复;
      1. 如果重复则不新增;
      2. 如果不重复则新增到链表的最后。
  1. //判断是否重复的规则
  2. if (p.hash == hash &&
  3. ((k = p.key) == key || (key != null && key.equals(k))))
  4. e = p;

判断是否重复的规则可以理解为

比较两个元素的的哈希值是否相同 && (地址值相同 || equals相同)

true为重复,不新增;false为不重复,新增。

可以借助下图来理解

注意:equals()方法是object类的方法,比较的是地址值。如果要比较内容需要重写hashCode()方法和equals()方法。

四、哈希表的扩容

哈希表的底层数组会在一下两种情况下扩容:

  1. 当同一索引值下的元素超过8个且数组长度小于64;
  2. 数组的索引值占有率超过0.75时(0.75为加载因子,加载因子是可以自己设置的,0.75是默认值)

扩容后的新容量 = 旧容量 << 1;

扩容后的新容量就等于旧容量的二倍。

可以借助下面的图来理解:

  1. final Node<K,V>[] resize() {
  2. Node<K,V>[] oldTab = table;
  3. int oldCap = (oldTab == null) ? 0 : oldTab.length;
  4. int oldThr = threshold;
  5. int newCap, newThr = 0;
  6. if (oldCap > 0) {
  7. if (oldCap >= MAXIMUM_CAPACITY) {
  8. threshold = Integer.MAX_VALUE;
  9. return oldTab;
  10. }
  11. else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
  12. oldCap >= DEFAULT_INITIAL_CAPACITY)
  13. newThr = oldThr << 1; // double threshold
  14. }
  15. else if (oldThr > 0) // initial capacity was placed in threshold
  16. newCap = oldThr;
  17. else { // zero initial threshold signifies using defaults
  18. newCap = DEFAULT_INITIAL_CAPACITY;
  19. newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
  20. }
  21. if (newThr == 0) {
  22. float ft = (float)newCap * loadFactor;
  23. newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
  24. (int)ft : Integer.MAX_VALUE);
  25. }
  26. threshold = newThr;
  27. @SuppressWarnings({"rawtypes","unchecked"})
  28. Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
  29. table = newTab;
  30. if (oldTab != null) {
  31. for (int j = 0; j < oldCap; ++j) {
  32. Node<K,V> e;
  33. if ((e = oldTab[j]) != null) {
  34. oldTab[j] = null;
  35. if (e.next == null)
  36. newTab[e.hash & (newCap - 1)] = e;
  37. else if (e instanceof TreeNode)
  38. ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
  39. else { // preserve order
  40. Node<K,V> loHead = null, loTail = null;
  41. Node<K,V> hiHead = null, hiTail = null;
  42. Node<K,V> next;
  43. do {
  44. next = e.next;
  45. if ((e.hash & oldCap) == 0) {
  46. if (loTail == null)
  47. loHead = e;
  48. else
  49. loTail.next = e;
  50. loTail = e;
  51. }
  52. else {
  53. if (hiTail == null)
  54. hiHead = e;
  55. else
  56. hiTail.next = e;
  57. hiTail = e;
  58. }
  59. } while ((e = next) != null);
  60. if (loTail != null) {
  61. loTail.next = null;
  62. newTab[j] = loHead;
  63. }
  64. if (hiTail != null) {
  65. hiTail.next = null;
  66. newTab[j + oldCap] = hiHead;
  67. }
  68. }
  69. }
  70. }
  71. }
  72. return newTab;
  73. }

 如图所示,当数组长度为16,索引值0下面的元素超过8个,数组就会扩容,数组长度变为32,而索引值0会与索引值16平分索引值0下的元素。直到数组长度达到64,那么此时,索引值0会与索引值32平分,索引自16会与索引值48平分。

什么情况下链表转红黑树?

当数组的长度大于64且同一索引值位置下元素超过8.

如图所示:

 

  1. else if (p instanceof TreeNode)
  2. e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/405194
推荐阅读
相关标签
  

闽ICP备14008679号