HashMap 的理解与结构

hashMap 1.8版本:

底层是数组+链表+红黑树 

  数组中存的是对象(node)对象里面有key value 和 next 是指向下一个的标记  还有一个int  类型的hash值

   hashmap插入链表的时候采用的是  尾插法。

  需要找一个中间的平衡点, 当我们的数组长度小于平衡值 用链表,  大于平衡值用 红黑树

  

什么时候使用链表:当我们的链表的个数小于8 的时候使用链表

什么时候使用红黑树:当我们的链表个数大于8的时候就转成红黑树

  为什么是链表个数是8 , 因为在源代码中了解到, 使用的是(泊松分布 poisson distribution)当链表个数是8 的时候 重复的概率是一亿个中只有6个重复的

链表和红黑树的转换:

当数组长度不够的时候怎么扩容:  会创建一个是原来2倍的数组   ,  len = 2的n次幂  原来的数据的  0.75f 倍 

  当我们的数组长度的扩容之后:

    需要把原来的数据存在新的数组中, 需要今天判断当 我们的链表 hash & oldcap 等于0 放到原有的位置, 不等于0的时候就放早老数组加1的位置上, 

    当的数组是红黑树的时候: 就重新打乱重新放在新的数组中

 

 

hashMap 1.7 的理解:

hashMap 的底层是数组+ 链表, 又称为 链地址法。

HashMap 是继承了map的接口,允许null键和null值。map放入的值得顺序是无序的。 HashMap的线程是不安全的。

HashMap 需要重新计算 hash 值。

 

hashmap在取值的时候 get方面根据 key(hashcode)–>hash–>indexFor–>最终索引位置   e.hash == hash  没有必要 ,如果没这个判断可以可能到的数据是null的, 

如果传入的key对象重写了equals方法却没有重写hashCode,而恰巧此对象定位到这个数组位置,如果仅仅用equals判断可能是相等的,但其hashCode和当前对象不一致,这种情况,根据Object的hashCode的约定,不能返回当前对象,而应该返回null。

 

 


对红黑树的理解:

    主要就是recolor  标色  和 rotation  旋转 , 旋转分为 左旋转 和右旋转。 

    根节点 是黑色的 ; 相邻的父节点和子节点不能同时为红



 hashMap 的遍历方法一:

  效率高。

Map map = new HashMap();
  Iterator iter = map.entrySet().iterator();
  while (iter.hasNext()) {
  Map.Entry entry = (Map.Entry) iter.next();
  Object key = entry.getKey();
  Object val = entry.getValue();
  }

hashMap 遍历方法二:

   效率低, 尽量不采用。

Map map = new HashMap();
  Iterator iter = map.keySet().iterator();
  while (iter.hasNext()) {
  Object key = iter.next();
  Object val = map.get(key);
  }

 

 hashMap的put过程:

 

 

HashMap的数据结构在jdk1.8之前是数组+链表,为了解决数据量过大、链表过长是查询效率会降低的问题变成了数组+链表+红黑树的结构,利用的是红黑树自平衡的特点。

链表的平均查找时间复杂度是O(n),红黑树是O(log(n))。

HashMap中的put方法执行过程大体如下:

1、判断键值对数组table[i]是否为空(null)或者length=0,是的话就执行resize()方法进行扩容。

2、不是就根据键值key计算hash值得到插入的数组索引i。

3、判断table[i]==null,如果是true,直接新建节点进行添加,如果是false,判断table[i]的首个元素是否和key一样,一样就直接覆盖。

4、判断table[i]是否为treenode,即判断是否是红黑树,如果是红黑树,直接在树中插入键值对。

5、如果不是treenode,开始遍历链表,判断链表长度是否大于8,如果大于8就转成红黑树,在树中执行插入操作,如果不是大于8,就在链表中执行插入;在遍历过程中判断key是否存在,存在就直接覆盖对应的value值。

6、插入成功后,就需要判断实际存在的键值对数量size是否超过了最大容量threshold,如果超过了,执行resize方法进行扩容。

 

 

 

    

posted @ 2020-09-28 10:30  那一的眸相遇  阅读(185)  评论(0编辑  收藏  举报