ArrayDeque的分析

本文详细解析了 Java 中 ArrayDeque 的实现原理,包括其通过循环数组实现的数据结构、容量分配算法及扩展机制等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 <span style="font-size:18px;">ArrayDeque继承了集合的抽象类AbstractCollection<E> ,实现了 Deque<E>, Cloneable, Serializable三个接口。</span>

从名字可以看出该队列是由循环数组实现的。


<span style="font-size:18px;">  private void allocateElements(int numElements) {
        int initialCapacity = MIN_INITIAL_CAPACITY;
        // Find the best power of two to hold elements.
        // Tests "<=" because arrays aren't kept full.
        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
        }
        elements = (E[]) new Object[initialCapacity];
    }</span>

       这段代码实现了分配一个合适的2的N次幂的容量的数组。>>>表示无符号右移,最高位补零(>>表示有符号右移,正数补零,负数补1)。右移一位相当于除以2,因为int 占据4哥字节,32位,最高位符号位,所以最大表示2^31-1。

      

<span style="font-size:18px;">            initialCapacity |= (initialCapacity >>>  1);
            initialCapacity |= (initialCapacity >>>  2);
            initialCapacity |= (initialCapacity >>>  4);
            initialCapacity |= (initialCapacity >>>  8);
            initialCapacity |= (initialCapacity >>> 16);</span>

这一段代码相当于把initialCapacity的最高位(非零)开始所有位都置为1 ,比如:100011011111到111111111111。当 initialCapacity大于2^30时,会返回2^31是负数,所以要进行判断。




当队列容量不够就进行扩展,乘以2

   private void doubleCapacity() {
        assert head == tail;
        int p = head;
        int n = elements.length;
        int r = n - p; // number of elements to the right of p
        int newCapacity = n << 1;
        if (newCapacity < 0)
            throw new IllegalStateException("Sorry, deque too big");
        Object[] a = new Object[newCapacity];
        System.arraycopy(elements, p, a, 0, r);
        System.arraycopy(elements, 0, a, r, p);
        elements = (E[])a;
        head = 0;
        tail = n;
    }
在尾部增加元素,红的代码是关键,解决循环跨界的问题。
   public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        if ( <span style="color:#FF0000;">(tail = (tail + 1) & (elements.length - 1))</span> == head)
            doubleCapacity();
    }


 

  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值