ArrayDeque源码详解

【ArrayDeque源码详解】今日长缨在手,何时缚住苍龙。这篇文章主要讲述ArrayDeque源码详解相关的知识,希望能为你提供帮助。


?
源码:\\sources\\android-25
ArrayDeque和ArrayList有区别也有相似的地方,他们都是数组存储数组,不同的是ArrayList存储是从数组位置的0开始的,而ArrayDeque有一个head和tail,head和tail可以指向数组的任何位置,head是指向数组的第一个元素,是有值的,tail是指向数组最后一个元素的下一个,是空的,如果tail大于head,那么数组大小就是tail-head,如果tail是小于head,那么数组大小为(head到数组长度+位置0到tail),代码不多,直接上代码

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
* Written by Josh Bloch of Google Inc. and released to the public domain,
* as explained at http://creativecommons.org/publicdomain/zero/1.0/.
*/

package java.util;

import java.io.Serializable;
import java.util.function.Consumer;

// BEGIN android-note
// removed link to collections framework docs
// END android-note

/**
* Resizable-array implementation of the @link Deque interface.Array
* deques have no capacity restrictions; they grow as necessary to support
* usage.They are not thread-safe; in the absence of external
* synchronization, they do not support concurrent access by multiple threads.
* Null elements are prohibited.This class is likely to be faster than
* @link Stack when used as a stack, and faster than @link LinkedList
* when used as a queue.
*
* < p> Most @code ArrayDeque operations run in amortized constant time.
* Exceptions include
* @link #remove(Object) remove,
* @link #removeFirstOccurrence removeFirstOccurrence,
* @link #removeLastOccurrence removeLastOccurrence,
* @link #contains contains,
* @link #iterator iterator.remove(),
* and the bulk operations, all of which run in linear time.
*
* < p> The iterators returned by this classs @link #iterator() iterator
* method are < em> fail-fast< /em> : If the deque is modified at any time after
* the iterator is created, in any way except through the iterators own
* @code remove method, the iterator will generally throw a @link
* ConcurrentModificationException.Thus, in the face of concurrent
* modification, the iterator fails quickly and cleanly, rather than risking
* arbitrary, non-deterministic behavior at an undetermined time in the
* future.
*
* < p> Note that the fail-fast behavior of an iterator cannot be guaranteed
* as it is, generally speaking, impossible to make any hard guarantees in the
* presence of unsynchronized concurrent modification.Fail-fast iterators
* throw @code ConcurrentModificationException on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: < i> the fail-fast behavior of iterators
* should be used only to detect bugs.< /i>
*
* < p> This class and its iterator implement all of the
* < em> optional< /em> methods of the @link Collection and @link
* Iterator interfaces.
*
* @authorJosh Bloch and Doug Lea
* @since1.6
* @param < E> the type of elements held in this deque
*/
public class ArrayDeque< E> extends AbstractCollection< E>
implements Deque< E> , Cloneable, Serializable

/**
* The array in which the elements of the deque are stored.
* The capacity of the deque is the length of this array, which is
* always a power of two. The array is never allowed to become
* full, except transiently within an addX method where it is
* resized (see doubleCapacity) immediately upon becoming full,
* thus avoiding head and tail wrapping around to equal each
* other.We also guarantee that all array cells not holding
* deque elements are always null.
*/
//存储的元素,并且elements的长度必须是2的n次方,这个和之前看到HashMap很相似,
//之前看的HashMap的数组长度也是2的n次方,因为要用到与运算,详细可以看
//javascript:void(0)/article/details/51165630
transient Object[] elements; // non-private to simplify nested class access

/**
* The index of the element at the head of the deque (which is the
* element that would be removed by remove() or pop()); or an
* arbitrary number equal to tail if the deque is empty.
*/
//指向队列头,这个头并不是数组的第0个元素,如果这样head就没有意义了,这个从
//下面的addFirst(E e)方法也可以看出,如果当head等于0的时候,在添加到first,那么
//会添加到数组的最后,并且head也指向数组的最后,这个下面在分析
transient int head;

/**
* The index at which the next element would be added to the tail
* of the deque (via addLast(E), add(E), or push(E)).
*/
//指向队列尾的下一个空间,可以这样理解,head指向的是第一个元素,tail指向的是最后
//一个元素的下一个,指的是空的。
transient int tail;

/**
* The minimum capacity that well use for a newly created deque.
* Must be a power of 2.
*/
//最小存储空间,必须是二的n次方,
private static final int MIN_INITIAL_CAPACITY = 8;

// ******Array allocation and resizing utilities ******

/**
* Allocates empty array to hold the given number of elements.
*
* @param numElementsthe number of elements to hold
*/
//分配空间,这个空间大小是比numElements大的最小的2的n次方,比如numElements
//是17,则初始化大小为32,因为2的4次是16小于17,2的5次是32,才大于17,如果传入
//的正好是2的n次方,那么初始化的空间大小的2的n+1次方,
private void allocateElements(int numElements)
//根据numElements初始化空间
int initialCapacity = MIN_INITIAL_CAPACITY;
// Find the best power of two to hold elements.
// Tests "< =" because arrays arent kept full.
//如果numElements小于8,直接初始化数组elements,否则,根据numElements
//的大小来计算数组的大小
if (numElements > = initialCapacity)
initialCapacity = numElements;
//下面代码很简单,其实就是移位把最左边位的1填充到后面,计算的时候你完全可以把
//numElements第一个1后面的所有1都忽略,我举个例子,比如17,二进制是(总共32位,
//前面全是0)10001,就可以转化为(总共32位,前面全是0)11111,就相当于把最左边
//的1全部填充到后面,
initialCapacity |= (initialCapacity > > > 1);
initialCapacity |= (initialCapacity > > > 2);
initialCapacity |= (initialCapacity > > > 4);
initialCapacity |= (initialCapacity > > > 8);
initialCapacity |= (initialCapacity > > > 16);
initialCapacity++; //加1,达到2的n次方
// 越界了,太大了,
if (initialCapacity < 0)// Too many elements, must back off
initialCapacity > > > = 1; // Good luck allocating 2^30 elements

elements = new Object[initialCapacity];


/**
* Doubles the capacity of this deque.Call only when full, i.e.,
* when head and tail have wrapped around to become equal.
*/
//空间扩大一倍,仅仅当满的时候,这时候head和tail都会指向同一个元素
private void doubleCapacity()
assert head == tail; //满了
int p = head;
int n = elements.length; //数组的长度
//关键是r不好理解,举个例子,在数组中,head不一定是之前0位置的,他可以指向其他位置,比如
//原来空间大小为16,head为13,也就是第14个元素(一数组是从0开始的),那么r就是16-13=3,也
//就是从head往后还有多少元素,待会copy的时候也是先从最后的r个元素开始
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); //先copy后面的r个
System.arraycopy(elements, 0, a, r, p); //在copy前面的p个
elements = a;
//重新调整head和tail的值

    推荐阅读