Java-集合类源码List篇(三)
前言
前面分析了ArrayList和LinkedList的实现,分别是基于数组和双向链表的List实现。但看之前那张图,还有两个实现类,一个是Vector,另一个是Stack,接下里一起走进它们的源码世界吧!
4. Vector
Vector跟ArrayList比较相似,继承实现的类或者接口也都是一样的,都是继承自AbstractList,同时底层也是基于数组来实现的。
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
4.1 Vector成员变量
/**
* 数组来保存集合中的元素
*/
protected Object[] elementData; /**
* 集合size
*/
protected int elementCount; /**
* 增长步长
*/
protected int capacityIncrement;
Vector既然是基于数组来实现的,那么肯定有一个数组的成员变量elementData,返回集合中当前元素的个数elementCount。与ArrayList不同的是增加了一个增长步长,我们知道在ArrayList中,每次增长是上一次的容量的1.5倍,而Vector中则是如果指定了capacityIncrement且该值为正整数,则每次需要扩容时的容量增长为该数值。
4.2 Vector访问元素
/**
* 添加元素
*/
public synchronized boolean add(E e) {
modCount++;
//判断是否需要扩容
ensureCapacityHelper(elementCount + 1);
//将元素添加至指定位置
elementData[elementCount++] = e;
return true;
}
看到上述方法是否很熟悉,没错,它其实跟ArrayList的添加元素方法基本差不多。唯一不同的就是该方法加了synchronized关键字,该关键字的意思就是访问该方法时需要获取到对象锁的线程方能访问。这就是Vector的线程安全访问机制,通过为每个方法添加synchronized关键字的方法达到在多线程对集合类进行操作时,能够线程安全访问。其它的基本与ArrayList无异。
5. Stack
看Vector的成员变量的时候,发现都是protected修饰的,所以是可以被子类直接访问的。
public
class Stack<E> extends Vector<E>
的确在Stack中是没有另外成员变量的,与Vector相比只不过增加了对栈操作的方法,所以Stack是基于数组的线程安全的栈实现集合。
Stack是一个基于LILO(后进先出)的栈的实现,它初始化的时候也是一个空的栈。可以看下他的构造函数:
/**
* Creates an empty Stack.
*/
public Stack() {
}
5.1 Stack的成员方法
|
public E push(E item); |
添加元素(入栈) |
|
public synchronized E pop(); |
移除元素(出栈) |
|
public synchronized E peek(); |
返回栈顶元素 |
|
public synchronized int search(Object o); |
查找元素 |
看到上述的成员方法,就知道它的方法同Vector一样都是同步的,所以它也是一种线程安全的实现。上面5个方法中,push是没有synchronized修饰的,而其他四个方法都是被synchronized修饰,这个是为什么呢?我们来看下push的源码实现:
public E push(E item) {
//调用Vector中的实现
addElement(item);
return item;
}
/**
* Vector中的addElement实现
* @param obj
*/
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
所以我们知道,push()方法其实调用的还是父类Vector的实现,所以就没有加synchronized修饰也能达到同步的效果啦!
再来看下search()方法实现:
public synchronized int search(Object o) {
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}
返回对象在栈中的位置,下标从1开始,栈顶元素为1。
其中数组的最后一位元素即为栈顶元素,search方法返回的是离栈顶最近的item与栈顶之间的距离!
在JDK中,有如下语句:
* <p>A more complete and consistent set of LIFO stack operations is
* provided by the {@link Deque} interface and its implementations, which
* should be used in preference to this class. For example:
* <pre> {@code
* Deque<Integer> stack = new ArrayDeque<Integer>();}</pre>
*
如果想要实现一个LIFO的基于数组栈实现的话,JDK中提供了ArrayDeque是应该优先考虑的。事实上ArrayDeque同LinkedList一样,都是可以作为LIFO(后进先出)的栈实现,同时也是可以作为FIFO(先进先出)的队列实现。那么就有个问题了:
为什么同样基于数组实现,Stack只能实现栈而ArrayDeque却可以作为栈和队列的实现呢?
要想实现FIFO的队列实现,那么必须满足能够在队列首部出队列,尾部进队列,就是要两端能够操作。

假定有以上数组,那么如果基于栈实现的话,则只需要维护该数组的尾端,出栈移除最大索引元素,size--,入栈则只需要判断size+1与length的大小,看是否需要扩容。如果要做到队首进行出队列,队尾入队列的操作,则每次出队列后,为保持数组空间的连续性都需要将全部元素往前移动一位,那么效率上则不是一种很理想的实现。
事实上,ArrayDeque是虽然也是采用基于数组实现的,而它的则增加了逻辑上的循环,通过增加head和tail使其变成了“循环数组”。所以在ArrayDeque中尾部指向索引tail不一定比首部索引head更大。至于具体实现就到后面Deque的接口实现类部分再详述啦!
小结
本篇中,主要是分析了基于的数组的集合实现类Vector和Stack,下面小结一下:
Stack与LinkedList用作堆栈时异同:
1.实现机制:Stack是基于数组实现的,LinkedList是基于链表实现的。
2.线程安全:Stack是在方法上进行了同步访问,LinkedList则没有,若需要同步,可通过Collections的同步方法实现。
Vector与ArrayList区别:
1.线程安全:Vector是在方法上进行了同步访问,ArrayList则没有,若需要同步,可通过Collections的同步方法实现。
2.成员变量:Vector增加了一个capacityIncrement成员属性,在扩容时该变量指定情况则直接增加相应步长容量。ArrayList则是增加约1.5倍容量。
经过三篇的篇幅,List接口的下的常用集合我们已经分析完啦!
Java-集合类源码List篇(三)的更多相关文章
- Java集合类源码解析:Vector
[学习笔记]转载 Java集合类源码解析:Vector 引言 之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector.为什么说是它兄弟呢?因为从容器的构造来说,Vec ...
- Java集合类源码解析:HashMap (基于JDK1.8)
目录 前言 HashMap的数据结构 深入源码 两个参数 成员变量 四个构造方法 插入数据的方法:put() 哈希函数:hash() 动态扩容:resize() 节点树化.红黑树的拆分 节点树化 红黑 ...
- java集合源码分析(三):ArrayList
概述 在前文:java集合源码分析(二):List与AbstractList 和 java集合源码分析(一):Collection 与 AbstractCollection 中,我们大致了解了从 Co ...
- Java集合源码分析(三)LinkedList
LinkedList简介 LinkedList是基于双向循环链表(从源码中可以很容易看出)实现的,除了可以当做链表来操作外,它还可以当做栈.队列和双端队列来使用. LinkedList同样是非线程安全 ...
- java集合类源码学习三——ArrayList
ArrayList无疑是java集合类中的一个巨头,而且或许是使用最多的集合类.ArrayList继承自AbstractList抽象类,实现了List<E>, RandomAccess, ...
- Java集合源码分析(三)Vevtor和Stack
前言 前面写了一篇关于的是LinkedList的除了它的数据结构稍微有一点复杂之外,其他的都很好理解的.这一篇讲的可能大家在开发中很少去用到.但是有的时候也可能是会用到的! 注意在学习这一篇之前,需要 ...
- Java集合类源码解析:ArrayList
目录 前言 源码解析 基本成员变量 添加元素 查询元素 修改元素 删除元素 为什么用 "transient" 修饰数组变量 总结 前言 今天学习一个Java集合类使用最多的类 Ar ...
- Java集合类源码解析:AbstractList
今天学习Java集合类中的一个抽象类,AbstractList. 初识AbstractList AbstractList 是一个抽象类,实现了List<E>接口,是隶属于Java集合框架中 ...
- java集合类源码学习二
我们查看Collection接口的hierarchy时候,可以看到AbstractCollection<E>这样一个抽象类,它实现了Collection接口的部分方法,Collection ...
- Java集合类源码分析
常用类及源码分析 集合类 原理分析 Collection List Vector 扩充容量的方法 ensureCapacityHelper很多方法都加入了synchronized同步语句,来保 ...
随机推荐
- Error: unable to connect to node rabbit@10: nodedown 修改hostname后异常
https://blog.csdn.net/witsmakemen/article/details/22651365 [root@d bin]# rabbitmqctl start_appStarti ...
- Qt 如何像 VS 一样创建项目模版?
qt 存储模版路径位置:Qt\Qt5.9.5\Tools\QtCreator\share\qtcreator\templates\wizards 在里面随意复制一个模版,修改三项即可在 qt 中显示该 ...
- Django 模板系统(template)
介绍 官方文档 常用模板语法 只需要记两种特殊符号: {{ }} 和 {% %} 变量相关的用{{}} 逻辑相关的用{%%} 变量 {{ 变量名 }} 变量名由字母数字和下划线组成. 点(.)在模 ...
- PAT 1071. 小赌怡情(15) JAVA
1071. 小赌怡情(15) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 常言道“小赌怡情”.这是一个很简单的 ...
- WebService中WSDL和WADL(转)
转自https://blog.csdn.net/liuxiao723846/article/details/51611183#commentBox 自己加了修改批注方便自己理解. 1.Java开发We ...
- sed Demo
@1:sed basic usage: 和AWK一样, sed也是逐行对文本进行处理. sed的主要功能如下: @1:对每行中的匹配项进行处理(修改/删除) @2:格式化文本的处理 @3:(行的增删改 ...
- Use Private Members from Base Class
最近看了一段代码:在导出类中调用继承自基类的某个public函数,该函数中对基类中的private数据成员 进行了赋值并将结果打印.看到程序的运行结果后,顿时感觉自己之前(我之前的理解这里就不说明了) ...
- redis的安装配置(转)
一.下载windows版本的Redis 去官网找了很久,发现原来在官网上可以下载的windows版本的,现在官网以及没有下载地址,只能在github上下载,官网只提供linux版本的下载 官网下载地址 ...
- hive与hbase
作者:有点文链接:https://www.zhihu.com/question/21677041/answer/185664626来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...
- 47求1+2+3+...+n
题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 用递归 public class Soluti ...