ArrayDeque简介说明

转自:

ArrayDeque简介说明

下文笔者讲述ArrayDeque简介说明

ArrayDeque简介

ArrayDeque是Deque接口的一种实现
依赖于可变数组来实现的
ArrayDeque没有容量限制,可根据需求自动进行扩容
ArrayDeque可作为栈来使用,效率要高于Stack
ArrayDeque可以作为队列来使用,效率相较于基于双向链表的LinkedList也要更好一些

ArrayDeque的成员变量

	//数组存储元素
	transient Object[] elements;
	//头部元素索引
	transient int head;
	//尾部元素索引
	transient int tail;
	//最小容量
	private static final int MIN_INITIAL_CAPACITY = 8;
ArrayDeque底层使用数组存储元素
  同时还使用head和tail来表示索引
  但注意tail不是尾部元素的索引
   而是尾部元素的下一位
即下一个将要被加入的元素的索引

ArrayDeque如何初始化

public ArrayDeque() {
    elements = new Object[16];
}

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

public ArrayDeque(Collection<? extends E> c) {
    allocateElements(c.size());
    addAll(c);
}

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 = new Object[initialCapacity];
}

ArrayDeque的初始化容量必须是2^n
 你传的初始化容量如果是10
 那么实际申请的数组容量是16
 如果申请的容量是33,那么实际的容量是62
 如果申请的容量是62,那么实际申请的容量是128。
我们可以从allocateElements方法中看出以上的运行原理

ArrayDeque中add方法

public void addFirst(E e) {
    if (e == null)
        throw new NullPointerException();
    elements[head = (head - 1) & (elements.length - 1)] = e;
    if (head == tail)
        doubleCapacity();
}

public void addLast(E e) {
    if (e == null)
        throw new NullPointerException();
    //tail中保存的是即将加入末尾的元素的索引
    elements[tail] = e;
    //tail向后移动一位
    if ( (tail = (tail + 1) & (elements.length - 1)) == head)
        //tail和head相遇,空间用尽,需要扩容
        doubleCapacity();
}

注意事项:
   tail的计算公式(tail = (tail + 1) & (elements.length - 1))
   当tail到达容量最后一个的时候,tail就为等于0,否则tail的值tail+1

ArrayDeque扩容机制

private void doubleCapacity() {
    assert head == tail; //扩容时头部索引和尾部索引肯定相等
    int p = head;
    int n = elements.length;
    //头部索引到数组末端(length-1处)共有多少元素
    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 = a;
    //重置头尾索引
    head = 0;
    tail = n;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值