20230314 java.util.ArrayDeque
源码学习
构造方法
ArrayDeque 有三个构造方法
- ArrayDeque() :默认底层数组大小是16
- ArrayDeque(int numElements) :不是指定底层数组大小,而是指最少要容纳的元素数量,具体大小是大于这个数量的2的n次幂
- ArrayDeque(Collection<? extends E> c) :底层数组具体大小是不小于集合元素数量的2的n次幂
calculateSize
calculateSize 方法用于计算大于元素数量的2的n次幂
底层数组的大小始终是2的n次幂,这样做是为了方便进行位运算
private static int calculateSize(int numElements) {
int initialCapacity = MIN_INITIAL_CAPACITY;
if (numElements >= initialCapacity) {
initialCapacity = numElements;
initialCapacity |= (initialCapacity >>> 1);
initialCapacity |= (initialCapacity >>> 2);
initialCapacity |= (initialCapacity >>> 4);
initialCapacity |= (initialCapacity >>> 8);
initialCapacity |= (initialCapacity >>> 16);
initialCapacity++;
if (initialCapacity < 0) // Too many elements, must back off
initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
}
return initialCapacity;
}
这里的位运算非常有趣,int是4个字节,也就是32位,>>>表示无符号右移
- 第一次右移1位,并和自身进行或位运算,就能保证前2位如果存在1,1会在最终结果中相同位上
- 第二次在第一次计算的基础上右移2位,并和自身进行或位运算,就能保证前4位如果存在1,1会在结果中
- ...
- 第五次将1扩大到32位,也就是int的位长度
一系列的位运算结束后,结果必定是000111(前面n个0,后面32-n个1),1从哪一位开始取决于入参int的最高位1在哪一位
位运算结束后,结果+1,就能得到大于且最接近入参int的2的n次幂
如果入参是Integer.MAX_VALUE
() ,+1后,会越界成为 Integer.MIN_VALUE
(),然后判断小于0,再无符号右移一位,也就是
因此,底层数组的大小值域是2的n次幂,且n在区间[4, 30]
二进制表示,负数可以表示的比整数多一个
添加方法 add、push
ArrayDeque中的方法名称中带有First和Last并不是指0和15,而是head和last两个索引,因为使用的是位运算,所以实际这两个索引值可以看作环形索引
- add方法从head向后添加,使用tail从0增加到15
- push方法从last向前添加,使用head从15减小到0
- pop方法和remove方法相同,都是从head向后删除
遍历、迭代器
从head向后环形遍历到tail
扩容、缩容
doubleCapacity 方法进行扩容,将容量扩大到2倍
从head到tail复制到新数组的从0开始的空间
可以看出来,底层数组的索引并不重要,一直操作的都是head和tail两个索引值
不会缩容
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理