数据结构与hashmap简单笔记

索引的本质

】 索引是帮助MySql高效的获取数据的排好序的数据结构

数据结构

二叉树
高度大,查询慢,会变成链表

红黑树
也叫二叉平衡树,自动平衡数据。

但是高度不可控,查询慢

B-Tree

也叫多路平衡二叉树

在进行范围查找的时候,不能快速的查到数据

在这里插入图片描述
B+Tree(B-Tree变种)

不是叶子节点不储存数据,值储存索引,这样就可以放更多的索引。

每个索引旁边又有一个指针指向下一个节点,这个节点也存放了上一节点的索引。

这个指针指向一个范围子节点区,每个范围子节点都有一个双向指针,

这个双向指针左边指向小的范围区,右边指向大的范围区。

也就是说,这个范围区的双向指针可以进行范围查询。

在这里插入图片描述

MyISAM数据库引擎

索引与数据分开保存,B+Tree只存索引,也就是非聚合索引

性能好,但是没有事务。

InnoDB数据库引擎

索引与数据都放在B+Tree叶子节点,就是聚合索引

必须有主键,并且推荐是整型,如果是String类型主键可能会变成4层节点,并且需要判断大小,浪费时间。

有事务,回滚,奔溃修复能力,与外部键

HashMap

java7是数组+链表

java8是数组+链表+红黑树,当链表的长度>=8就会转成红黑树

通过hash%数组长度获得index
通过:index = hash%length

如果出现了相同的hash值,那就会出现hash碰撞,当出现碰撞之后,一个数组下标就会储存两个元素,这两个元素就会变成链表。

但是链表的查询速度很慢(O(n)),所以当链表的长度>=8就会转成红黑树。

数组长度
数组长度=定义的长度<=2的指数次幂

也就是大于或等于定义长度的2^n,其中最接近的数就是数字长度
在这里插入图片描述

用&来计算索引的下标位置,因为&计算的是二进制的。

&运算结果是: 两个同时为1,结果为1,否则为0

在这里插入图片描述

就比如默认初始是16的大小,长度-1就是15。

这时又一串hashcode:1101 0010 1010 0110

15的长度变成二进制: 0000 0000 0000 1111

当进行&运算变成了: 0000 0000 0000 0110

最后下标是:6

这样保证元素位置在0-15之间,并且速度快。

为什么加载因子是0.75?

加载因子是表示Hash表中元素填满的长度。

诺加载叶子越大,填满的元素就越多,好处是空间利用率高了,但hash冲突的机会加大了,反之加载因子越小填满的元素越少,好处是冲突减小,空间浪费多了。

冲突的机会越大,则查找的成本越高.反之,查找的成本越小.因而,查找时间就越小.

因此,必须在 "冲突的机会"与"空间利用率"之间寻找一种平衡与折衷. 这种平衡与折衷本质上是数据结构中有名的"时-空"矛盾的平衡与折衷.

所有的Hash表都理论上都不可能避免冲突(无论Hash函数如何设计).当表中都快填满时(加载因子大),再填入新的元素时,冲突的机会将很大.
JAVA的HashMap当put(…)时若产生冲突(即:两个不同的对象,但其hadhCode相同,表明想占用表中同一个位置空间),则目前的实现中是:占用Hash表中同一个位置空间的冲突的元素,用一个链表来链起来.这样:当get(…)时,若有冲突,就要访问链表了(这样,一旦有冲突,put(…)与get(…)都要和链表打交道,成本当然就高了)

因此:要尽最大努力,减少冲突的机会

https://www.baidu.com/link?url=pvL5lkGKu1oX1Z8hjn8V5AjvXLt6GOmYqarkwtWIKwkWpfYYJd8ASt4bbVb0pLQNupHkwR9NNv_PqVS7Ftvp3Abq1AMSd8Pnc8Rf_oPHOhK&wd=&eqid=8631fe7800098d1e000000065ec33bed

为什么链表长度到达8就变成红黑树?

泊松分布

是一种概率学,未来可以会发生的事情
在这里插入图片描述

所以得出,链表的长度越大,发生hash碰撞的概率就越低,到了长度8碰撞就概率就接近于0.

所以链表转成红黑树概率也小,只有在这个hash表的数据非常大的时候才会转成红黑树。

JDK7的hash出现环型链表

在put值后,会进入addEntry进行判断是否需要扩容,

如果我这个大小,大于等于我计算的元素填充长度(16-1)* 0.75 = 12, 并且这个元素插入的下标不为空

在这里插入图片描述
那环型链表就是在扩容时出现的。

因为扩容会进行一个迁移,把旧数组迁移到新数组。

移位

在这里插入图片描述

迁移后的顺序是反的。

先e指向的第一个元素移到新的数组,再让下一个元素的next指向当前元素,到时移位的时候,下一个元素的next就是它上一个元素的。所以顺序反了。

但是如果是多线程就会变成环。

比如第一个线程进来但是阻塞后,第二个线程完成了迁移。

但是第一个线程有指向数组的指针,这时的指针e还是第一个元素,而next时第二个元素。

第一个线程有又会重新进行迁移.

那就变成了e=元素1,next=null

再次循环判断e不为空,e.next=元素1,e=元素2。

再次判断又变成e=元素1,e.next=null,然后结束循环。

但是读取时就会出现环型链路

Java8hashmap

并且没有重新hash,速度快。

会重新进行迁移.

那就变成了e=元素1,next=null

再次循环判断e不为空,e.next=元素1,e=元素2。

再次判断又变成e=元素1,e.next=null,然后结束循环。

但是读取时就会出现环型链路

Java8hashmap

并且没有重新hash,速度快。

出现一个地位指针和高位指针,会把链表拆分,并且保存到其他数组节点,而不是原来的节点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值