ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java之ArrayDeque

2019-09-15 10:06:33  阅读:351  来源: 互联网

标签:ArrayDeque Java 16 initialCapacity 索引 tail elements


文章目录

一、底层数据结构

// 构造方法
public ArrayDeque() {
        elements = (E[]) new Object[16];
    }

该队列是基于数组实现的.

二、方法思维导图

在这里插入图片描述
从方法来看, ArrayDeque既可以用作队列(元素添加至尾部)、也可以作为(元素添加至头部).

三、 部分方法的源代码

1. add

public boolean add(E e) {
        addLast(e);
        return true;
    }
public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        if ( (tail = (tail + 1) & (elements.length - 1)) == head) // 判断下一个索引是否超出数组范围
            doubleCapacity(); // 扩容
    }

为什么(tail = (tail + 1) & (elements.length - 1)) == head能够判断索引是否超出范围?

Firstly, 首先记住 2n2^n2n & (2n2^n2n-1) == 0 . 比如4&3==0, 16&15==0.

Secondly, 构造方法保证了无论如何内部数组的长度总是2n2^n2n, 且长度必定>=8

Lastly, 举个栗子. 例如, 长度为16的数组, 最后一个元素的索引为(length - 1)即tail=15, 套用上面的代码16 = (15 + 1) & 16 -1, 即16 & 15.Get it?

// 构造方法一
public ArrayDeque() {
       elements = (E[]) new Object[16]; // 长度为2^4
    }
// 其它构造方法调用
private void allocateElements(int numElements) {
        int initialCapacity = MIN_INITIAL_CAPACITY; // 8
        // Find the best power of two to hold elements.
        // Tests "<=" because arrays aren't kept full.
        if (numElements >= initialCapacity) {  // 长度必定大于等于8
            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   // Integer.MAX_VALUE + 1
                initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
        }
        elements = (E[]) new Object[initialCapacity];
    }

2. remove

虽然ArrayDeque与ArrayList都是基于数组实现的, 但是ArrayDeque并不提供根据索引访问数据, 也就是说不能像ArrayList一样根据索引访问数据例如:get(i), 因为ArrayDeque没有实现RandomAccess接口.

// 关键代码
public E pollFirst() {
        int h = head;
        E result = elements[h]; // Element is null if deque empty
        if (result == null)
            return null;
        elements[h] = null;     // Must null out slot
        head = (h + 1) & (elements.length - 1); //修改头部索引
        return result;
    }

它虽然基于数组实现, 却使用2个变量来记录队列的头部和尾部的索引, 头部索引并非一定为0.
private transient int head // 记录首个元素所在索引
private transient int tail //记录下一个元素添加时的索引

还有一点,分清数组长度(elements.length)集合大小(size())的区别.

3. size()

public int size() {
   return (tail - head) & (elements.length - 1);
 }

标签:ArrayDeque,Java,16,initialCapacity,索引,tail,elements
来源: https://blog.csdn.net/csdnLeraner/article/details/100690103

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有