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 [隐藏目录] 前情提要 简介 存储结构 源码分析 主要内部类 构造方法 添加元素 添加元素举例 删除元素 删除元素举例 查找元素 查找元素 ...
随机推荐
- Python 实现类似PHP的strip_tags功能,并能够定义他们自己的一套保留标记
最近的研究 Python ,发现还是很习惯使用,多PHP这是非常easy该功能Python 这不得不找了半天,而且非常灵活不得不实现自己的. 我们今天聚集,需要过滤的内容标签,搞一个PM.外形似终于想 ...
- [Visual Studio]透过Visual Studio 2012的选择性贴上将XML与JSON直接转成对应的类别
原文:[Visual Studio]透过Visual Studio 2012的选择性贴上将XML与JSON直接转成对应的类别 在开发专案时若碰到要串接服务或是他人的API,常常避免不了都要面对XML或 ...
- C语言功能 --C
功能名称: cabs 动力 能够: 计算绝对复数值 使用 法国: double cabs(struct complex z); 程序示例: #include <stdio.h> #incl ...
- Html.Partial和Html. RenderPartial用法
Html.Partial和Html. RenderPartial用法 Html.partial和RenderPartial的用法与区别Html.partial和RenderPartial都是输出htm ...
- Oracle中的delete和truncate的关系
转自:http://chenxy.blog.51cto.com/729966/168459 1.相同点 a.都可以删除数据,其中truncate用于全表清空数据,而delete可以选择的删 ...
- oracle当需要commit
今天oracle的SQL plus 运行该删除和查询操作,然后PL/SQL还运行查询.相同的句子,结果是不一样的.我郁闷很大,然后,突然想到这可能对双方造成由数据不一致,为什么不一致呢.就是没用com ...
- hdu 逆袭指数
Problem Description 这依然是关于高富帅小明曾经的故事—— 尽管身处逆境,但小明一直没有放弃努力,除了搬砖,小明还研究过东方的八卦以及西方的星座,一直试图在命理上找到自己能够逆袭 ...
- c/c++和java达到swap不同功能
首先我们来看看c/c++实施swap性能 void swap ( int & a, int & b) { int Temp; temp = a; a = b; b = temp; } ...
- Oracle Global Finanicals Technical Reference(一个)
Skip Headers Oracle Global Finanicals Oracle Global Financials Technical Reference Manual Release 11 ...
- LeetCode_算法及数据结构覆盖统计
[输入]共计151道题的算法&数据结构基础数据 (见附录A) [输出-算法]其中有算法记录的共计 97道 ,统计后 结果如下 top3(递归,动态规划,回溯) 递归 动态规划 回溯 BFS ...