天天看点

集合:HashMap原理

1、底层结构(数组、链表、红黑树,这是jdk8新添加的内容,在jdk1.7中是数组加上链表实现的)

(1)底层结构:

集合:HashMap原理

  当桶的数量达到64,且链表的长度达到8时,链表结构将变为红黑树(jdk8),当长度降到6的时候转成链表,链表的时间复杂度是O(n),红黑树的时间复杂度O(logn),红黑树更优。长度降到6的时候再变为链表是因为红黑树的节点比链表节点大,占用空间更大,而且链表比较短的时候查询也足够快,因此没必要直接使用红黑树的结构。(两个条件要同时满足才会转化为红黑树,否则,仅仅发生一次resize散列表的扩容,如果初始的数组容量为16,就把数组的大小扩展为2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知hashmap中元素的个数,那么预设元素的个数能够有效的提高hashmap的性能)

  哈希冲突理论上是不可以避免的

       hashMap中每一个数据单元就是一个Node结构,Node结构中有key、value、next、hash字段(值不是hashCode的返回值,是将高低16位异或运算得到。采用高低位的异或运算能够优化哈希算法,因为哈希值一般都在16位(table.length-1运算后)以内(低),这样的话哈希值的高16位就会浪费掉),next字段是发生哈希冲突的时候当前同为桶位中的node与冲突的node连成一个链表要用到的字段

  散列表(哈希表)是懒加载机制,只有在第一次put数据的时候才会创建

  默认的负载因子是0.75,作用是计算扩容的阈值,使用无参的方法创建HashMap的话,默认是16*0.75=12

(2)红黑树

  • 解决链化(链表很长)问题,提高查找效率,链化特别严重的时候查询就会接近O(n),而红黑树为O(log n)
  • 构成树的结点拥有颜色属性(红黑)
  • 根结点必须是黑色的
  • 从叶子结点到根结点的路径上,每条路径上的黑色结点数量一致
  • 不能有两个红色结点相连,也就是说红色结点的两个子结点一定是黑色结点,叶子结点一定是黑色结点,新的节点一定是红色(碰到父节点是黑色的话树不会失衡)

(3)hashmap扩容原理

数组变长,链表变短(以空间换时间),提升查找效率

 (4)特点

hashMap的初始容量(数组,即桶的个数)和加载因子会影响hashMap的性能,加载因子用于衡量哈希表的满的程度,因为桶太满的话查找的效率会降低,达到满的程度的时候就要扩容

 加载因子默认为0.75,数组长度的初始值为16

2、map.put执行过程

(1)执行过程

集合:HashMap原理

(2)路由寻址:

 路由寻址公式:(table.length-1)&node.hash

table.length:为2的n次方

:3、put方法的返回值

public class MyTest {         public static void main(String[] args) throws IOException {              HashMap<String,String> hashMap=new HashMap<>();              hashMap.put("1","2");              String value=hashMap.put("1","3");              System.out.println(value);         }     }      

输出的结果是2不是3,执行的流程是3覆盖了2,但是返回的数值并不是新的值,而是以前的旧的value。

4、执行流程

(1)hashCode方法:

public class MyTest {         public static void main(String[] args) throws IOException {              System.out.println("zhai".hashCode());         }     }      
3737558      

这个值是不能直接作为哈希表的下标的,因为哈希表的长度不会那么长。hash%table.length才是要查找的哈希表的下标

(2)put操作(1.7头插法,1.8尾插法)

集合:HashMap原理

每个人都会有一段异常艰难的时光 。 生活的压力 , 工作的失意 , 学业的压力。 爱的惶惶不可终日。 挺过来的 ,人生就会豁然开朗。 挺不过来的 ,时间也会教你 ,怎么与它们握手言和 ,所以不必害怕的。 ——杨绛