ArrayDeque源码解析

1、概述

ArrayDeque 是 Deque 接口的变长数组实现,它没有容量限制,会根据需要来扩容。它不是线程安全的,缺乏外部的同步机制,导致它不支持多线程的并发访问。Null 对象是不许存在的,这个类很可能比 Stack 实现的栈和 LinkedList 实现的队列更快。

其绝大多数操作运行在常数时间,除了一些需要线性时间执行的方法:removeremoveFirstOccurrenceremoveLastOccurrencecontainsiterator.remove()和批量操作。

它继承了 AbstractCollection,实现了DequeCloneableSerializable

public class ArrayDeque<E> extends AbstractCollection<E>
                           implements Deque<E>, Cloneable, Serializable

2、变量

// deque存放数据的数组,它的容量就是数组的长度,总是2的幂次方。数组不允许被充满,除非暂时性的用add方法导致数组充满,这里就要立刻扩容,去避免head和tail变得相同。同时,这里也保证数组中没有元素的位置始终为空。
transient Object[] elements;
transient int head;  // deque的头部,remove和pop的位置,deque为空时和tail相等
transient int tail;  // deque的尾部,addLast、add和push的位置
private static final int MIN_INITIAL_CAPACITY = 8;  // 新建deque的最小容量,必须为2的幂次方

3、构造方法

public ArrayDeque() {
   
    elements = new Object[16];  // 默认长度16
}

public ArrayDeque(int numElements) {
   
    allocateElements(numElements);
}

// 类似HashMap的方法分配数组长度,2的幂次方且刚比指定的长度大
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);  // 按位或,有一个为1就为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 = new Object[initialCapacity];
}

public ArrayDeque(Collection<? extends E> c) {
   
    allocateElements(c.size());
    addAll(c);  // AbstractCollection中的方法
}

4、重要方法

数组分配和大小调整的方法:

private void doubleCapacity() {
     // 当新增数据导致头尾重合时就要double数组容量
    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);  // 从头开始到最后移到a最前
    System.arraycopy(elements, 0, a, r, p);  // 从最前到头移到上述的后面
    elements = a;  // 头尾分别是0、n
    head = 0;
    tail = n;
}

// 将原来数组的元素拷贝到新数组,有序的(从头到尾)
private <T> T[] copyElements(T[] a) {
   
    if (head < tail) {
   
        System.arraycopy(elements, head, a
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值