HashMap底层红黑树与MySQL索引
前置知识:什么是时间复杂度?如何计算时间复杂度?
常见的时间复杂度及关系:O(1)<O(logn)<O(n)<O(n^2)
以吃面包为例,问吃面包需要的时间:
O(1):一口吃一个面包,时间最短。
O(logn):一口吃掉面包的一半,时间比较短。
O(n):一口吃掉面包的一寸,时间比较长。
O(n^2):一口吃掉面包的一寸,第二口开始减半,吃半寸,第三口吃四分之一寸……时间最长。
前置知识:常见的查找算法有哪些?
遍历:暴力 for 时间复杂度O(n)
二分法(二叉搜索树/二叉查找树):能做二分查找必须是有序的 O(logn)
哈希:最高效。 O(1) JDK1.8里面HashMap:链表+红黑树,几种算法的组合拳。
索引:搜索引擎
bfs&dfs:图论里面的遍历
平衡树
B+树
B-Tree
红黑树:高效的查找算法。
哈希
Hash也译作散列,是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
哈希可以有多种算法进行实现。
优秀的哈希算法可以让输出很均匀地散列在值域。
哈希算法是无法逆向推导的。
HashMap为什么查找快?
因为通过对key取哈希可以很快得到hashcode,从而得到存放位置,进而得到指针(内存地址),最终就快速找到了内容value。
二分法/ 二叉搜索树/二叉查找树
数据必须有序才可使用。猜大小游戏。时间复杂度为O(logn)。极端情况会成为链表,时间复杂度O(n)。
红黑树
特殊的二叉查找树,通过左旋或右旋实现自动平衡,避免链表化。
索引
能作为数据库索引的数据结构有哪些?
数组(不适合大数据量),链表(不适合大数据量)。
Hash(不能范围查找)
红黑树(数据库是存磁盘的,树太高,树的每一层都读一次,读磁盘次数太多。磁盘上一页能存16kb数据,读一次16kb,只取一个4字节的int,非常浪费。)
所以数据库MySQL中采用的可以:
B树(就是B-Tree),B+树
B树
n叉的排序树。
B+树
HashMap底层
JDK中常见的集合容器包括哪些?
主要有List Set和Map三个接口以及实现了这些接口的诸多子类。
List Set是实现了Collection接口,Map是单独的接口。
List Set Map在概念上的差别?
List是有序的,元素可重复;
Set是无序的,元素不可重复;(最多只能有一个元素为null)
Map是无序的,存储的元素为Entry键值对,其中键不可重复。(最多只能有一个键值为null)
HashMap数据结构
HashMap在底层维护了一个长度为16的数组(名为table),里面存放的是Entry(Entry是接口,Node是实现)对象,也就是键值对。在存放时需要先把key进行hash运算,得到hashcode,用hashcode对数组长度进行取模得到的数字作为该Entry对象在数组中的位置。
优秀的hash算法可以使元素均匀地分布于数组中。如果HashMap底层数组中每个位置最多只有一个元素,则查找元素的时间复杂度为O(1)。
当出现n个元素的位置相同时,这n个元素都会形成一个链表挂载到数组的某位置。查找的时间复杂度O(n)。
JDK1.8对此进行了优化,如果挂载的链表太长,超过8个,就会将这个链表转化成红黑树。查找元素的时间复杂度O(logn)。这样就起到了一定的优化作用。
为什么这个长度设置为8呢?和泊松分布有关,是类库的设计者在时间和空间开销上作的取舍。
loadFactor负载因子默认为0.75,当数组table的格子被占用达到16*0.75=12个的时候进行2倍扩容。(简单理解)
tip:transient修饰符修饰的属性是不会被序列化的。序列化、反序列化之后是不可见的。