【集合系列】- 深入浅出分析 ArrayDeque

一、摘要

在 jdk1.5 中,新增了 Queue 接口,代表一种队列集合的实现,咱们继续来聊聊 java 集合体系中的 Queue 接口。

Queue 接口是由大名鼎鼎的 Doug Lea 创建,中文名为道格·利,关于这位大神,会在后期进行介绍,翻开 JDK1.8 源代码,可以将 Queue 接口旗下的实现类抽象成如下结构图:

Queue 接口,主要实现类有:ArrayDeque、LinkedList、PriorityQueue。

关于 LinkedList 实现类,在之前的文章中已经有所介绍,今天咱们来介绍一下 ArrayDeque 这个类,如果有理解不当之处,欢迎指正。

二、简介

在介绍 ArrayDeque 类之前,可以从上图中看出,ArrayDeque 实现了 Deque 接口,Deque 是啥呢,全称含义为double ended queue,即双端队列。Deque 接口的实现类可以被当作 FIFO(队列)使用,也可以当作 LIFO(栈)来使用。

其中队列(FIFO)表示先进先出,比如水管,先进去的水先出来;栈(LIFO)表示先进后出,比如,手枪弹夹,最后进去的子弹,最先出来。

ArrayDeque 是 Deque 接口的一种具体实现,所以,既可以当成队列,也可以当成栈来使用,类定义如下:

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

当作为队列使用时,我们会将它与 LinkedList 类来做对比,在后文,我们会做测试类来将两者进行详细数据对比。因为 Deque 接口继承自 Queue接口,在这里,我们分别列出两者接口所定义的方法,两者内容区别如下:

当作为栈使用时,难免会将它与 Java 中一个叫做 Stack 的类做比较,Stack 类的数据结构也是后进先出,可以作为栈来使用,我们分别列出 Stack 类和 Deque 接口所定义的方法,两者内容区别如下:

虽然,ArrayDeque 和 Stack 类都可以作为栈来使用,但是 ArrayDeque 的效率要高于 Stack 类,并且功能也比 Stack 类丰富的多,当需要使用栈时,Java 已不推荐使用 Stack,而是推荐使用更高效的 ArrayDeque,次选 LinkedList 。

从上面两张图中可以看出,Deque 总共定义了 2 组方法,添加、删除、取值都有两套方法,它们功能相同,区别是对失败情况的处理不同,一组方法是遇到失败会抛异常,另一组方法是遇到失败会返回null

方法虽然定义的很多,但无非就是对容器的两端进行添加、删除、查询操作,明白这一点,那么使用起来就很简单了。

继续回到咱们要介绍的这个 ArrayDeque 类,从名字上可以看出 ArrayDeque 底层是通过数组实现的,为了满足可以同时在数组两端插入或删除元素的需求,该数组还必须是循环的,即循环数组,也就是说数组的任何一点都可能被看作起点或者终点。

因为是循环数组,所以 head 不一定总是指向下标为 0 的数组元素,tail 也不一定总是比 head 大。

这一点,我们可以通过 ArrayDeque 源码分析得出这些结论,打开 ArrayDeque 的源码分析,可以看到,主要有3个关键参数:

  • elements:用于存放数组元素。
  • head:用于指向数组中头部下标。
  • tail:用于指向数组中尾部下标。
public class ArrayDeque<E> extends AbstractCollection<E>
                           implements Deque<E>, Cloneable, Serializable{
    /**用于存放数组元素*/
    transient Object[] elements;

    /**用于指向数组中头部下标*/
    transient int head;

    /**用于指向数组中尾部下标*/
    transient int tail;

    /**最小容量,必须为2的幂次方*/
    private static final int MIN_INITIAL_CAPACITY = 8;
}

与此同时,ArrayDeque 提供了三个构造方法,分别是默认容量,指定容量及依据给定的集合中的元素进行创建,其中默认容量为 16。

public ArrayDeque() {
    //默认初始化数组大小为 16
    elements = new Object[16];
}

指定容量初始化方法,源码如下:

public ArrayDeque(int numElements) {
    //指定容量
    allocateElements(numElements);
}

我们来看看指定容量调用的allocateElements方法,源码如下:

private void allocateElements(int numElements) {
    elements = new Object[calculateSize(numElements)];
}

calculateSize方法&#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值