1 Java的数据结构相关的类的实现原理
1.1 HashMap、TreeMap、LinkedHashMap
-
HashMap是不是有序的? 不是
-
有没有有顺序的Map实现类?有TreeMap和LinkedHashMap
-
TreeMap和LinkedHashMap是如何保证它的顺序的?
TreeMap是通过Comparator比较器来构建红黑树从而保证key的有序性,而LinkedHashMap是通过双向链表来保证元素插入的有序性。 -
TreeMap和LinkedHashMap的不同?
1.TreeMap是通过Comparator比较器来构建红黑树从而保证key的有序性,而LinkedHashMap是通过双向链表来保证元素插入的有序性。
2.TreeMap继承于AbstractMap,LinkedHashMap继承于HashMap.
3.TreeMap里面只维护红黑树这个数据结构,而LinkedHashMap是数组+单向链表+双向链表结构。
4.TreeMap的所有增删改查的操作都是对红黑树的操作,而LinkedHashMap的增删改查操作是先对数组的操作,再对双向链表的操作,遍历的时候是遍历的双向链表
5.TreeMap主要用在需要排序的场景(还可以实现一致性hash算法),LinkedHashMap主要用在需要加密、签名、jvm缓存场景 -
什么是一致性hash算法?
-
LinkedHashMap为什么适合使用在需要签名或加密的场景?因为他能保证插入元素的顺序性。
-
LinkedHashMap为什么适合做jvm本地缓存?本地缓存需要考虑是线程安全性和防止内存泄漏。而LinkedHashMap可以完美的实现类似于LRU缓存算法。
-
介绍一下Comparator比较器?
-
TreeMap和LinkedHashMap哪个的有序实现比较好?
1.底层结构:LinkedHashMap底层还是沿用了HashMap的存储结构,核心区别在于节点属性中通过额外添加前后元素的属性,采用链表方式保存了元素存放的顺序。而TreeMap底层采用的是红黑树结构,存放的元素会根据key的大小顺序。
2.有序性:LinkedHashMap能够保证遍历顺序和存放顺序的一致性,而TreeMap由于在存放元素的时候会根据Key值进行排序,所以不能保证遍历顺序和存放顺序的一致性。但两者都能保证多次遍历的顺序一致性。
3.性能比较:LinkedHashMap无论是在新增、修改、删除还是根据根据Key值进行等值查找时,都有比TreeMap更好的性能,但是在根据Key值进行区间检索、范围查询时TreeMap更有优势。
4.使用场景:HashMap是Key-Value数据结构的首选类型,性能最高,能满足绝大部分的场景,如果还需要保证集合的遍历和存放顺序的一致性可以采用LinkedHashMap,如果需要根据Key值顺序对集合内存放的元素进行排序则推荐采用TreeMap。 -
有没有更好的(有序Map)实现方式?
-
HashMap的底层原理?
存储的数据结构:
在JDK7中:HashMap是由数组、链表组成的
在JDK8中:HashMap是由数组、链表、红黑树组成的
查询通过哈希算法 -
数组的特性:查询快(O(1)),删除、插入慢(O(n))
-
为什么:查询快是因为数组都有一个序号也就是下标地址,是连续的,所以可以根据下标地址确定位置查询数据,时间复杂度为O(1);插入、删除慢是因为除非插入或删除的元素是数组的最后一个元素,否则所插入或删除元素后面的元素的下标都需要改变,时间复杂度为O(n)。
-
java中的哪一个util类采用数组来实现?ArrayList
-
ArrayList的特性:查询快,插入、删除慢。
-
为什么?因为ArrayList的底层是通过数组实现的。
-
链表的特性:插入、删除快,查询慢
-
为什么?插入和删除只需要变更上一个节点的next,但查询需要遍历链表
-
java中的哪一个util类采用的链表来实现?LinkedList
-
LinkedList的特性:插入、删除快,查询慢
-
为什么?因为LinkedList底层是通过链表来实现的
-
什么是哈希算法?哈希算法也叫散列,就是把任意长度值(key)通过散列算法变换成固定长度的key也就是地址,通过这个地址进行访问。它通过把关键码值映射到表中一个位置来访问记录,以加快查找速度。
-
哈希算法的特点:幂等性、不可逆。
-
什么是幂等性?
-
是否可逆?哈希算法是不可逆的。
-
HashCode:通过字符串算出它的ASCII码相加,进行mod(除以10取模),算出哈希表中的下标。
-
为什么取模?为了节省内存空间。
-
取模会出现什么问题?会出现hash冲突(碰撞)
-
什么是hash冲突?两个key值取模后的值相同,数组存在同一个下标下的内容会覆盖,而我们的HashMap是可以存取模后值相同的两个key值的,没有覆盖。
-
hash冲突是怎么解决的?通过链表解决的。假设keyA和keyB取模后的值相同为1,可以让keyA指向keyB,当keyB匹配下标为1的节点不相等时再去匹配下一个节点。
-
为什么JDK8用的是红黑树?解决链表过长查询效率过低的问题,阈值是8。
-
为什么阈值是8?在理想情况下,链表长度符合泊松分布,各个长度的命中概率依次递减,当长度为8的时候,概率仅为0.00000006,这是一个小于千万分之一的概率,通常我们的Map里面是不会存储这么多数据的,所以通常情况下,并不会发生从链表向红黑树的转变。
-
什么是泊松分布?如果随机事件A发生的概率是P,进行n次独立实验,恰巧发生了k次,则相应的概率可以用这样的一个公式来计算:
P ( x = k ) = λ k k ! ∗ e − λ P(x=k)= \dfrac{\lambda^k}{k!}*e^{-\lambda} P(x=k)=k!λk∗e−λ -
介绍一下红黑树?红黑树是一种自平衡二叉搜索树,是一种特殊的二叉搜索树,在进行插入和删除时通过特定操作保持二叉树自身的平衡,从而获得较高的查找性能。
-
红黑树的特性:
1.节点是红色或黑色
2.根节点是黑色
3.所有叶子节点都是黑色的空节点。(叶子节点是NIL节点或者NULL节点)
4.每个红色节点的两个字典点都是黑色节点(从每个叶子节点到根的路径上不能有两个连续的红色节点)
5.从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点 -
红黑树调整平衡的操作:左旋、右旋和变色