ArrayDeque源码详解
Posted 山大王算法
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.
*
* @author Josh Bloch and Doug Lea
* @since 1.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 numElements the 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的值
JDK源码ArrayDeque源码分析