PriorityQueue
利用了 二叉堆 的数据结构来实现的 , 底层使用 可变长的数组来存储数据 。PriorityQueue
通过堆元素的上浮和下沉 , 实现了在 O(logn)
的时间复杂度内插入元素和删除堆顶元素 。PriorityQueue
是 非线程安全的 , 且不支持存储 NULL
和 non-comparable
的对象 。PriorityQueue
默认是小顶堆 , 但可以接收一个 Comparator
作为构造参数 , 从而来自定义元素优先级的先后 。11
。 当数组比较小( 小于64 )的时候每次 扩容容量翻倍 。 当数组比较大( 大于等于64 )的时候每次扩容只 增加一半的容量 。PriorityQueue
不是有序的 , 只有堆顶存储着最小的元素HashSet
的实现是依赖于 HashMap
的 , HashSet 的值都是存储在HashMap中的 。 在 HashSet 的构造法中会初始化一个HashMap对象 , HashSet 不允许值重复 。 因此 , HashSet的值是作为HashMap的key存储在HashMap 中的 , 当存储的值已经存在时返回false 。???面试官追问:HashSet有哪些特点?
- 无序性 (存储元素无序)
- 唯一性 (允许使用 null )本质上 , HashSet的值是作为HashMap的key存储在HashMap 中的 , 因此保证唯一性
- HashSet没有提供
get()
方法 , 同HashMap一样 , 因为Set内部是 无序 的 , 所以只能通过 迭代 的方式获得
- JDK1.7:数组 + 链表
- JDK1.8:数组 + (链表 | 红黑树)
所谓扰动函数指的就是 HashMap 的 hash 方法 。 使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法 换句话说使用扰动函数之后可以减少碰撞 。
JDK1.8的hash方法:
static final int hash(Object key) {
int h;
// key.hashCode():返回散列值也就是hashcode
// ^ :按位异或
// >>>:无符号右移 , 忽略符号位 , 空位都以0补齐
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
JDK1.7的hash方法:
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
从源码可以看出JDK 1.8 的 hash 方法 相比于 JDK 1.7 hash 方法更加简化 , 但是原理不变 。 JDK 1.7 的 hash 方法的性能会稍差一点点 , 因为毕竟扰动了 4 次 。
13.HashMap 的长度为什么是 2 的幂次方?
- 计算索引时效率更高 :
hash % tab.length
, 而计算机中直接求余运算效率不如位移运算 。 所以源码中做了优化 , 使用hash & (tab.length- 1)
来寻找桶位 。 而实际上hash % length
等于hash & ( length - 1)
的 前提是 length 必须为 2 的 n 次幂
- 扩容时重新计算索引效率更高 :
- 顶固集创与中国电信研究院、中山大学战略合作|定制快讯| 中国电信研究院
- 因全球范围内专利发明表现突出 蚂蚁集团入选2022年《全球百强
- 苹果|不用iPhone!苹果员工集体要换安卓手机:原因曝光
- javascript|JavaScript设置页面元素的滚动条一直最下方
- 安卓|不用iPhone!苹果员工集体要用安卓手机:原因是为防公司窥探
- 集成电路|春节后这些行业人才需求看涨,上海求职者最“卷”
- 监管部门|警惕以元宇宙名义非法集资
- 小米投资光莱弗利科技,经营范围含集成电路销售
- exynos|三星芯片遭手机部门嫌弃?集团内部讨论,可能砍掉Exynos项目!
- 集团企业采购的高端商务本有哪些门道?