Java集合之Stack 源码分析
1.简介
栈是数据结构中一种很重要的数据结构类型,因为栈的后进先出功能是实际的开发中有很多的应用场景。Java API中提供了栈(Stacck)的实现,简单使用如下所示
package com.test.collections;
import java.util.Stack;
public class StackTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Stack<String> stack = new Stack<String>();
stack.add("China");
stack.add("Japan");
stack.add("Russia");
stack.add("England");
System.out.println(stack.size()+"<="+stack.capacity());
System.out.println(stack.elementAt(0));
System.out.println(stack.get(0));
System.out.println(stack.peek());
System.out.println(stack.push("France"));
System.out.println(stack.pop());
System.out.println(stack.iterator());
System.out.println(stack.empty());
System.out.println(stack.isEmpty());
System.out.println(stack.search("Russia"));
}
}
2.继承结构
Stack类继承了Vector类,而Vector类继承了AbstractList抽象类,实现了List接口,Cloneable接口,RandomAcces接口以及Serializable接口,需要指出的Vector内部还有两个内部类ListItr和Itr,Itr在继承Vector的同时实现了Iterator接口,而ListItr在继承了Itr类的同时实现了ListIterator接口。
3.源码解读
通过Stack类发现含有的方法有pop(),peek(),push(Object),search(Object),empty()方法,其他值的方法是从Vector类继承而来,通过源码可以发现Vector有几个属性值:protected Object[] elementData,protected int elementCount;protected int capacityIncrement;private static final int MAX_ARRAY_SIZE = 2147483639;通过这几属性我们可以发现,Stack底层是采用数组来实现的,elementData用于保存Stack中的每个元素;elementCount用于动态的保存元素的个数,capacityIncrement用来保存Stack的容量(一般情况下应该是大于elementCount);MAX_ARRAY_SIZE 用于限制Stack能够保存的最大值数量。
a.removeElementAt()
public synchronized void removeElementAt(int paramInt) {
this.modCount += 1;
if (paramInt >= this.elementCount)
throw new ArrayIndexOutOfBoundsException(paramInt + " >= "
+ this.elementCount);
if (paramInt < 0)
throw new ArrayIndexOutOfBoundsException(paramInt);
int i = this.elementCount - paramInt - 1;
if (i > 0)
System.arraycopy(this.elementData, paramInt + 1, this.elementData,
paramInt, i);
this.elementCount -= 1;
this.elementData[this.elementCount] = null;
}
removeElementAt()方法用于移除某个位置的元素,需要指出元素的位置,这个方法来之与Stack的父类Vector;通过代码我们可以发现它的实现是首先判断参数是否合法然后将这个位置前的所有元素都向后移动了一位,而且把元素的个数-1,最后把原来位置最上面的那个元素置为空,从而实现了删除某个元素的操作。
b:elementData(int)
E elementData(int paramInt) {
return this.elementData[paramInt];
}
elementData(int)返回某一位置的元素的具体值,通过这个方面也可以看出Stack底层是有一个数组来实现的 。
c:elementAt(int)
public synchronized E elementAt(int paramInt) {
if (paramInt >= this.elementCount)
throw new ArrayIndexOutOfBoundsException(paramInt + " >= "
+ this.elementCount);
return elementData(paramInt);
}
elementAt(int paramInt)首先判断参数是否合法,然后就直接调用elementData(paramInt)返回具体的对象值。
d:peek()
public synchronized E peek() {
int i = size();
if (i == 0)
throw new EmptyStackException();
return elementAt(i - 1);
}
通过源码就可以发现peek()只是获取了第一个位置的元素的值(Stack的下标和数组保持一致都是从0开始,最大到元素总数-1)
e:pop()
public synchronized E pop() {
int i = size();
Object localObject = peek();
removeElementAt(i - 1);
return localObject;
}
pop()方法的实现是首先获取Stack的元素数量,然后调用peek()方法获取栈顶的第一个元素,然后调用removeElementAt(int)删除栈顶元素,最后将元素的值返回。
f:addElement(E paramE)
public synchronized void addElement(E paramE) {
this.modCount += 1;
ensureCapacityHelper(this.elementCount + 1);
this.elementData[(this.elementCount++)] = paramE;
}
addElement(E)方法是个很重要的方法,因为它实现了元素的添加。它在添加元素的时候首先将modCount加1,ensureCapacityHelper()主要用于保障Stack的容量,如果超过当前容量则调用grow()方法进行容量增加,如果操作最大的容量MAX_ARRAY_SIZE就会抛出异常。第三步才会实现元素的添加,就是i将该元素添加到栈顶,并且将元素的数目加1;
g:search(Object)
public synchronized int search(Object paramObject) {
int i = lastIndexOf(paramObject);
if (i >= 0)
return (size() - i);
return -1;
}
该方法返回所查找对象所处的位置,如果不存在在返回-1;通过代码可以发现它的实现过程是这样的,首先通过lastLindexOf(Object)方法返回从栈底到栈顶最下面的的那个元素的下标,然后利用元素的总数目减去所处的下标就得到了元素的位置(),并且返回否则返回-1;(需要注意的改位置返回的是从栈顶到栈底开始所处的位置,栈顶元素的位置为1)
h:empty()
public boolean empty() {
return (size() == 0);
}
直接返回元素的数目与0比较的关系,size()方法是通过this.elementCount返回了栈元素的数目。
4.其他(小结)
通过源码我们可以看到Vector底层是一个数组,说明Stack的实现是通过数组来实现的,然后通过对数组的操作来模仿栈的各种功能。而且在源码中Vector的很多方法都是synchronized 的,也就是说是线程安全,所以说在多线程中是可以安全使用的,不过这样效率上肯定是会降低的。
Java集合之Stack 源码分析的更多相关文章
- 死磕 java集合之DelayQueue源码分析
问题 (1)DelayQueue是阻塞队列吗? (2)DelayQueue的实现方式? (3)DelayQueue主要用于什么场景? 简介 DelayQueue是java并发包下的延时阻塞队列,常用于 ...
- 死磕 java集合之PriorityBlockingQueue源码分析
问题 (1)PriorityBlockingQueue的实现方式? (2)PriorityBlockingQueue是否需要扩容? (3)PriorityBlockingQueue是怎么控制并发安全的 ...
- 死磕 java集合之PriorityQueue源码分析
问题 (1)什么是优先级队列? (2)怎么实现一个优先级队列? (3)PriorityQueue是线程安全的吗? (4)PriorityQueue就有序的吗? 简介 优先级队列,是0个或多个元素的集合 ...
- 死磕 java集合之CopyOnWriteArraySet源码分析——内含巧妙设计
问题 (1)CopyOnWriteArraySet是用Map实现的吗? (2)CopyOnWriteArraySet是有序的吗? (3)CopyOnWriteArraySet是并发安全的吗? (4)C ...
- 死磕 java集合之LinkedHashSet源码分析
问题 (1)LinkedHashSet的底层使用什么存储元素? (2)LinkedHashSet与HashSet有什么不同? (3)LinkedHashSet是有序的吗? (4)LinkedHashS ...
- 死磕 java集合之ConcurrentHashMap源码分析(三)
本章接着上两章,链接直达: 死磕 java集合之ConcurrentHashMap源码分析(一) 死磕 java集合之ConcurrentHashMap源码分析(二) 删除元素 删除元素跟添加元素一样 ...
- 死磕 java集合之ArrayDeque源码分析
问题 (1)什么是双端队列? (2)ArrayDeque是怎么实现双端队列的? (3)ArrayDeque是线程安全的吗? (4)ArrayDeque是有界的吗? 简介 双端队列是一种特殊的队列,它的 ...
- 死磕 java集合之LinkedList源码分析
问题 (1)LinkedList只是一个List吗? (2)LinkedList还有其它什么特性吗? (3)LinkedList为啥经常拿出来跟ArrayList比较? (4)我为什么把LinkedL ...
- 【死磕 Java 集合】— ConcurrentSkipListMap源码分析
转自:http://cmsblogs.com/?p=4773 [隐藏目录] 前情提要 简介 存储结构 源码分析 主要内部类 构造方法 添加元素 添加元素举例 删除元素 删除元素举例 查找元素 查找元素 ...
随机推荐
- JUnit使用参数测试和一组测试
JUnit该参数测试和一组测试使用简单 参数测试 作为替代阵列int a0,a1,a2喜欢,当测试加法assertEquals(3.0, h.add(1, 2), 0.1);相当于声明一个变量,要測试 ...
- oracle触发农产品证明文件号码
CREATE OR REPLACE TRIGGER TRG_KC_SPRK_i BEFORE INSERT ON KC_SPRK FOR EACH ROW DECLARE vS ...
- NSIS:判断并安装.NET Framework 4 的例子
原文 NSIS:判断并安装.NET Framework 4 的例子 现在.NET开发的软件已经大行其道,但有些操作系统并不符合软件的运行要求,所以,我们需要在安装程序中进行.NET Framework ...
- Javascript设计模式与开发实践读书笔记(1-3章)
第一章 面向对象的Javascript 1.1 多态在面向对象设计中的应用 多态最根本好处在于,你不必询问对象“你是什么类型”而后根据得到的答案调用对象的某个行为--你只管调用行为就好,剩下的一切 ...
- js关于propotype的一些事-------Day62
近期在忙着搬家,忙忙活活的收拾这收拾那,原以为自己东西了了,谁知道东西是越收拾越多,各种崩溃啊..... 昨日在记录js动态生成表格的经典方式时,用到了createDocumentFragment() ...
- Flux demo
Flux demo Introduction flux应用架构如下图所示,本文并不是讲述怎么立即做一个酷炫的应用,而是讲述如何依照这种框架,来进行代码的组织.我们先把这个流程转述为文字:抛开与webA ...
- HDU 5052 Yaoge’s maximum profit 光秃秃的树链拆分 2014 ACM/ICPC Asia Regional Shanghai Online
意甲冠军: 特定n小点的树权. 以下n每一行给出了正确的一点点来表达一个销售点每只鸡价格的格 以下n-1行给出了树的侧 以下Q操作 Q行 u, v, val 从u走v,程中能够买一个鸡腿,然后到后面卖 ...
- SSH框架总结(帧分析+环境结构+示例源代码下载)
首先,SSH不是一个框架.而是多个框架(struts+spring+hibernate)的集成,是眼下较流行的一种Web应用程序开源集成框架,用于构建灵活.易于扩展的多层Web应用程序. 集成SSH框 ...
- CSharp设计模式读书笔记(6):建造者模式(学习难度:★★★★☆,使用频率:★★☆☆☆)
建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 模式角色与模式: 建造者模式可以将一个产品的内部表象与产品的生产过程分割开来, ...
- 电商指尖---(9).net发展Solr中间Facet特征
上一节中我们演示了在SolrAdmin中使用Facet功能来进行分组统计.这一节我们看看如何使用.NET开发Solr中的Facet功能.在讲Facet功能的同一时候, 我们看下.Net中如何使用Sol ...