5 手写Java Stack 核心源码
Stack是Java中常用的数据结构之一,Stack具有"后进先出(LIFO)"的性质。
只能在一端进行插入或者删除,即压栈与出栈
栈的实现比较简单,性质也简单。可以用一个数组来实现栈结构。
- 入栈的时候,只在数组尾部插入
- 出栈的时候,只在数组尾部删除**
我们来看一下Stack的用法 :如下
public static void main(String[] args){
//新建一个栈
Stack<String> stack = new Stack<>();
//分别向栈中添加不同的元素
stack.push("tom");
stack.push("jim");
stack.push("wendy");
stack.push("natasha");
//分别弹栈
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
}
输出如下:
natasha
wendy
jim
tom
从输出可以看到,最后入栈的,最先出栈
下面我们底层用数组也来实现这样一个栈,在数组的尾部插入和删除。
也就是入栈和出栈。如下图:
完整的源码如下:
public class QStack<E> {
//数组的默认大小为10
private static final int DEFAULT_INIT_CAPACITY = 10;
//底层的数组
private Object[] elements;
//栈中的个数
private int size;
public QStack() {
this(DEFAULT_INIT_CAPACITY);
}
public QStack(int capacity) {
//capacity条件检查 ,这里我们直接抛出异常
if (capacity <= 0) {
throw new IllegalArgumentException("capacity <= 0");
}
if (capacity > Integer.MAX_VALUE) {
throw new IllegalArgumentException("capacity > Integer.MAX_VALUE");
}
//新建一个capacity大小的数组
elements = new Object[capacity];
//初始个数为0
size = 0;
}
//栈是否为空
public boolean isEmpty() {
return size == 0;
}
//返回栈中的元素个数
public int size() {
return size;
}
//将一个元素压入栈中
public E push(E e) {
//如果栈已满,进行扩容
if (size >= elements.length) {
grow();
}
//扩容完后将元素e压入栈中
elements[size] = e;
//别忘了size需要加 1
size++;
return e;
}
//出栈,就是将数组最后一个元素弹出
public E pop() {
//如果栈为空就返回null
if (isEmpty()) {
return null;
}
//拿到栈的大小
int len = size();
//把数组中最后一个元素保存起来
E e = peek();
//个数别忘了减1
size--;
//将最后一个元素置null
elements[len - 1] = null;
//返回e
return e;
}
//返回最后一个元素
public E peek() {
int len = size();
if (len == 0)
throw new RuntimeException("stack is empty");
return (E) elements[len - 1];
}
//扩容
private void grow() {
//将之前的数组保存
int oldCapacity = elements.length;
Object[] old = elements;
//新的数组大小为原来数组大小的2倍
int newCapacity = oldCapacity * 2;
//再新建一个大小为原来数组2倍的新数组
elements = new Object[newCapacity];
//把以前的老的数组中的元素都移动新数组中
for (int i = 0; i < oldCapacity; i++) {
elements[i] = old[i];
}
//释放以前的内存空间
old = null;
}
}
以上面可知:用数组实现栈结构,主要需要注意以下 2 点:
- 在数组的尾部插入和删除,也就是压栈和弹栈
- 由于是用数组实现栈结构,数组满的时候,需要扩容
下面我们写一段测试代码来测试,如下:
public static void main(String[] args){
//创建一个栈
QStack<String> stack = new QStack<>();
//分别向栈中压入4个不同的元素
stack.push("tom");
stack.push("jim");
stack.push("wendy");
stack.push("natasha");
//分别弹栈
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
}
打印如下:
natasha
wendy
jim
tom
5 手写Java Stack 核心源码的更多相关文章
- 6 手写Java LinkedHashMap 核心源码
概述 LinkedHashMap是Java中常用的数据结构之一,安卓中的LruCache缓存,底层使用的就是LinkedHashMap,LRU(Least Recently Used)算法,即最近最少 ...
- 3 手写Java HashMap核心源码
手写Java HashMap核心源码 上一章手写LinkedList核心源码,本章我们来手写Java HashMap的核心源码. 我们来先了解一下HashMap的原理.HashMap 字面意思 has ...
- 2 手写Java LinkedList核心源码
上一章我们手写了ArrayList的核心源码,ArrayList底层是用了一个数组来保存数据,数组保存数据的优点就是查找效率高,但是删除效率特别低,最坏的情况下需要移动所有的元素.在查找需求比较重要的 ...
- 1 手写Java ArrayList核心源码
手写ArrayList核心源码 ArrayList是Java中常用的数据结构,不光有ArrayList,还有LinkedList,HashMap,LinkedHashMap,HashSet,Queue ...
- 4.1 手写Java PriorityQueue 核心源码 - 原理篇
本章先讲解优先级队列和二叉堆的结构.下一篇代码实现 从一个需求开始 假设有这样一个需求:在一个子线程中,不停的从一个队列中取出一个任务,执行这个任务,直到这个任务处理完毕,再取出下一个任务,再执行. ...
- 4.2 手写Java PriorityQueue 核心源码 - 实现篇
上一节介绍了PriorityQueue的原理,先来简单的回顾一下 PriorityQueue 的原理 以最大堆为例来介绍 PriorityQueue是用一棵完全二叉树实现的. 不但是棵完全二叉树,而且 ...
- Java HashMap 核心源码解读
本篇对HashMap实现的源码进行简单的分析. 所使用的HashMap源码的版本信息如下: /* * @(#)HashMap.java 1.73 07/03/13 * * Copyright 2006 ...
- 手撕spring核心源码,彻底搞懂spring流程
引子 十几年前,刚工作不久的程序员还能过着很轻松的日子.记得那时候公司里有些开发和测试的女孩子,经常有问题解决不了的,不管什么领域的问题找到我,我都能帮她们解决.但是那时候我没有主动学习技术的意识,只 ...
- Java内存管理-掌握类加载器的核心源码和设计模式(六)
勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇文章介绍了类加载器分类以及类加载器的双亲委派模型,让我们能够从整体上对类加载器有 ...
随机推荐
- 从头认识java-15.1 填充容器(2)-利用Collection的addAll方式
接着上一章节,我们继续介绍填充容器. 这一章节我们结束还有一种填充容器的方式:addAll 样例: package com.ray.ch15; import java.util.ArrayList; ...
- 【原创】Sublime Text 3快捷配置c++的编译,运行,gdb环境
打开Tools ->Build System -> New Build System 弹出一个文件,将原有的东西删掉,输入: { "encoding": "u ...
- 基于live555实现的跨平台高性能RTSPServer流媒体服务器EasyIPCamera
本文转自EasyDarwin团队成员kim的博客:http://blog.csdn.net/jinlong0603/article/details/52366412 简介 EasyIPCamera是由 ...
- jquery 使用ajax,正常返回后,不执行success的问题
背景: 在使用到jQuery的ajax时,如果指定了dataType为json,老是不执行success回调,而是执行了error回调函数. 原因: 然后继续下载了几个jquery版本,如1.3.2, ...
- 在c代码中获取用户环境变量
1 extern char ** environ 这是一个字符串数组,最后一个元素是null,即\0. 2 在代码中的使用方法 直接extern char **environ,然后 直接environ ...
- arm处理器的历史及现状
1 arm处理器的发展历史 arm1 arm2 arm3 arm6 arm7 arm9 arm11 arm cortex 2 arm处理器现状 arm cortex A a即application,即 ...
- asp概述
asp的理解 今天才知道,Asp原来不是一种语言,也不是一种开发工具,而是一种技术框架, 主要功能是把脚本语言,HTML,组件和Web数据库访问功能有机的结合在一起, 形成一个能在服务器端运行的应用程 ...
- Dynamic Web Module to 3.0 报错
一.问题 使用maven项目创建的webapp项目Dynamic Web Module 默认是2.3. 当我们要切换到3.0的时候出现这个错误. 二.解决 1.点击进入Navigator view ( ...
- Android在有存储卡和无存储卡情况下拍照后固定尺寸和压缩大小
我最近工作挺忙,距离上一次写博客转眼已经过了一个多月,每次学到和用到点新东西,其实都有分享的欲望,但奈何文笔太差,而一篇文章包括构思,排版,修改发布的时间最少要花费2个小时(这其中还不包括写完后未保存 ...
- Python序列——序列操作
Python中的序列包括,字符串.列表.元组.本文介绍序列的通用操作. 1. 切片中的None >>> s = 'abcdefg' >>> for i in ran ...