Java之集合(二)ArrayDeque
转载请注明源出处:http://www.cnblogs.com/lighten/p/7283928.html
1.前言
上章讲解了Java中的集合接口和相关实现抽象类,本章开始介绍一些具体的实现类,第一个介绍的就是继承自抽象类AbstractCollection的实现类ArrayDeque,其同时实现了Deque接口。Queue的结构是一个单端的队列,从一端进另一端出,Deque是一个双端队列。而ArrayDeque是一个使用循环数组实现的双端队列了。双端队列可以实现单端队列的先入先出的方式,也可以实现栈结构的先入后出的方式,使用比较灵活,看具体需求。ArrayDeque是线程非安全的,所以如果需要实现线程安全,就需要自己处理了。
2.实现讲解
2.1 接口
Deque接口在上章没有讲解,先从这里开始说明。该接口继承了Queue接口,而且由于其是双端队列,所以自然而然有如下接口:

这些接口看名称也很容易理解,操作首端和尾端对应的add、offer、remove、poll、element、peek这些方法。除了上面的这些接口,还定义了两个接口:push、pop。这两个接口用于当双端队列作为栈的形式使用时的入栈、出栈接口。剩下的一个接口就是descendingIterator接口了,其提供了一个倒序的迭代器。
2.2 ArrayDeque
循环数组的双端队列实现起来非常简单,里面的数据结构就只有下图:

一个数组,一个指向头的下标,一个指向尾的下标。就这么一个简单的结构实现了双端队列。值得注意的是数组的大小必须是2n,为何这么做网上说是由于内存的分配是以2的幂指数个页帧为单位进行的,标准的内存分配大小是4K,用2的幂指数为大小分配空间有利于内存管理。可能是由于这个问题,而我更想讲解的是其是如何保证输入的值是2n的。看下面的代码:

这一段代码乍一看感觉有些莫名其妙,但是正是由于这段代码保证了其分配的数组大小是2n。这段代码所计算的是:输入一个数字X计算X<Y=2n,使这个等式成立时n取最小的时候Y的值,Y就是分配的数组大小了。所以不管你输入多少(超过Java整数范围除外),最终会满足这个公式使得最终分配的结果是2n。上段代码所实现的功能知道了,但是其这么实现的具体原理是什么呢?如下:
1.要明确2n使用二进制的表现形式如下:0...010...0,中间有一个1,其它的都是0。
2.根据1的形式,计算使输入任意的X,等式成立的Y。X的二进制形式为????????,是一个未知数,这样如何求得Y呢?方法很简单,找到X最高位为1的位置:那么X就是0..001???,这种形式了。那么所求的Y就是0..010...0,其值就是比X最高位为1再高一位为1,其它位为0的值。
3.X的最高为1的那一位是未知的,如何求更高一位为1的Y呢?直接求是没有办法的,但是可以通过将X最高位为1后面所有位都变成1,再加1进位的方式办到。就是0..001???变成0.001..1,使用这个+1就会变成所要的Y:0.010...0了。
4.如何保证X最高位为1后面都是1呢?这个就是上面位运算所实现的内容了。假设X是0..01???,左移一位就是0.001??,做或运算就变成了0..011??,是不是很巧妙,出现了两位为1的就移动2位,获得四位为1的值,这样移动到16的时候就涵盖了32位整数的所有范围了。这个时候+1可能发生整数溢出,所以再左移一位保证在整数范围内。
以8位整数为例,假设输入的是8:00001000,运算过程如下:

这样就算出来了结果。循环列表扩容代码如下:

一个循环数组扩容时,先把队列头右边的放入扩容后的数组,再把队列头左边的内容放入数组后面。
关于循环数组的操作,其实了解队列的应该也很清楚,就是从头端入就是element[head-1]=Object,从尾端入就是element[tail+1]=Object。出也是对应的,然后就是对head和tail的值进行修改而已,其它的都不难理解,看代码就能清楚了。这里有一个问题就是数组越界的问题,-1或+1都会超过数组的长度,按照循环列表应该定位到数组的尾部或者头部,这里代码中借助了数组长度是2n,解决了这个问题。就是:得到的值 & (elements.length - 1),这样就保证了在数组范围内,且是正确的位置。这个很好理解,不做介绍。
2.3 操作图


这就是整个添加和扩容的流程了。移除的方法是一样的,就不再画图描述了。
Java之集合(二)ArrayDeque的更多相关文章
- Java之集合(二十六)ConcurrentSkipListMap
转载请注明源出处:http://www.cnblogs.com/lighten/p/7542578.html 1.前言 一个可伸缩的并发实现,这个map实现了排序功能,默认使用的是对象自身的compa ...
- Java之集合(二十七)其它集合
转载请注明源出处:http://www.cnblogs.com/lighten/p/7551368.html 1.前言 本章介绍剩余的3个集合类:ConcurrentSkipListSet.CopyO ...
- Java之集合(二十四)ConcurrentLinkedDeque
转载请注明源出处:http://www.cnblogs.com/lighten/p/7517454.html 1.前言 本章介绍并发队列ConcurrentLinkedDeque,这是一个非阻塞,无锁 ...
- Java之集合(二十三)SynchronousQueue
转载请注明源出处:http://www.cnblogs.com/lighten/p/7515729.html 1.前言 本章介绍阻塞队列SynchronousQueue.之前介绍过LinkedTran ...
- Java之集合(二十二)PriorityBlockingQueue
转载请注明源出处:http://www.cnblogs.com/lighten/p/7510799.html 1.前言 本章介绍阻塞队列PriorityBlockingQueue.这是一个无界有序的阻 ...
- Java之集合(二十五)ConcurrentHashMap
转载请注明源出处:http://www.cnblogs.com/lighten/p/7520808.html 1.前言 本章介绍使用的最频繁的并发集合类之一ConcurrentHashMap,之前介绍 ...
- Java之集合(二十一)LinkedTransferQueue
转载请注明源出处:http://www.cnblogs.com/lighten/p/7505355.html 1.前言 本章介绍无界的阻塞队列LinkedTransferQueue,JDK7才提供了这 ...
- Java之集合(二十)LinkedBlockingQueue
转载请注明源出处:http://www.cnblogs.com/lighten/p/7503678.html 1.前言 本章介绍阻塞队列LinkedBlockingQueue,这是一个基于链表的可选长 ...
- JAVA基础-集合(二)
一.Map整体结构体系 Map是集合的另一大派系,与Collection派系不同的是Map集合是以键值对儿的形式存储在集合的.两个键为映射关系,其中第一个键为主键(主键是唯一的不可重复),第二个键为v ...
随机推荐
- C++之类和对象的使用(三)
对象数组 如果构造函数只有一个参数,在定义数组时可以直接在等号后面的花括号内提供.Student stud[3]={90,92,01};//合法 如果构造函数有多个参数,则不能用在定义时直接所提供所有 ...
- select自定义下拉选择图标
闲言少叙: 上CSS: appearance: none; -moz-appearance: none; -webkit-appearance: none; cursor: pointer; back ...
- PAT甲 1006. Sign In and Sign Out (25) 2016-09-09 22:55 43人阅读 评论(0) 收藏
1006. Sign In and Sign Out (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...
- Chinese Seals
Emperors used seals to proclaim their decrees to their people, officials used seals to exercise thei ...
- Fading Like a Flower
Fading Like a Flower In a time where the sun descends alone 伴着落日孤独的脚步 I ran a long long way from hom ...
- JQuery fullcalender文档
转载: http://blog.csdn.net/lgg2011. 使用方式, 引入相关js, css后, $(‘#div_name’).fullCalendar({//options}); 接受的 ...
- C# 一些代码小结--串口操作
串口解析显示中文 private String SerialPortReadStr() { try { String str = null; int n = serialPort1.BytesToRe ...
- wpf简单进度条
UserControl x:Class="WpfApplication1.UserControl2" xmlns="http://schemas.microsoft.co ...
- 如何使用socket进行java网络编程(一)
笔者进来遇到一个项目,一家公司的系统需要在完成自身业务逻辑的同时,接入到某银行的核心系统(这里准确说应该是前置机)进行一系列的账务处理,然后再将账务处理结果返回给该公司系统. 网络通信采用TCP协议. ...
- OpenStack 数据库操作 demo
#!/usr/bin/env python from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine f ...