Java集合底层源码剖析-Vector和Stack

文章目录

  • 概述
  • Vector
    • 成员变量
    • 关键方法
    • 添加元素 (add, addElement)
    • 删除元素 (remove)
    • 注意事项
  • Stack
      • 类定义与继承
      • 压栈 (`push`)
      • 弹栈 (`pop`)
      • 查看栈顶元素 (`peek`)
      • 源码解析总结

概述

在Java中,Stack 类是一个基于 Vector 实现的经典栈数据结构。由于 Vector 类本身是线程安全的,并且是一个动态数组,因此继承自 Vector 的 Stack 类自然也就具备了这些特性

Vector

Java中的Vector类是一个线程安全的动态数组,它继承自AbstractList并实现了RandomAccess、Cloneable和Serializable、List接口。Vector内部使用一个数组来存储元素,并且设计为在多线程环境下安全使用。
它允许我们存储任何类型的对象,并提供了动态增长的能力。以下是Vector类的一些关键源码解析和重要特性:

成员变量

elementData:一个Object类型的数组,用于存储Vector中的元素。
elementCount:表示当前Vector中实际元素的数量。
capacityIncrement:每次Vector需要扩容时,除了默认的加倍扩容外,额外增加的容量大小。

关键方法

添加元素 (add, addElement)

public synchronized void addElement(E obj) {modCount++;ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = obj;
}private void ensureCapacityHelper(int minCapacity) {if (minCapacity - elementData.length > 0)grow(minCapacity);
}private void grow(int minCapacity) {// 计算新容量,至少为原容量的两倍或满足最小容量需求int oldCapacity = elementData.length;int newCapacity = oldCapacity + ((capacityIncrement > 0) ?capacityIncrement : oldCapacity);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 扩容操作elementData = Arrays.copyOf(elementData, newCapacity);
}

删除元素 (remove)

public synchronized boolean remove(Object o) {return removeElement(o);
}private boolean removeElement(Object obj) {modCount++;for (int i = 0; i < elementCount; i++) {if (obj.equals(elementData[i])) {fastRemove(i);return true;}}return false;
}private void fastRemove(int index) {modCount++;int numMoved = elementCount - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index,numMoved);elementData[--elementCount] = null; // Let gc do its work
}

注意事项

Vector中的大多数修改方法(如add, remove)都是同步的,这意味着它们在多线程环境中是线程安全的,但这也可能引入性能开销。
由于线程安全的设计,Vector在单线程环境下相比非线程安全的集合(如ArrayList)性能较差。
capacityIncrement参数允许用户自定义每次扩容的增长量,如果不指定,默认情况下每次扩容都会使容量翻倍。
当不再需要Vector对象时,应确保正确地将其设置为null,以便垃圾回收器能够回收其占用的内存资源。

Stack

Java中的Stack类是一个基于Vector实现的类,用于表示后进先出(LIFO,Last-In-First-Out)的数据结构。它提供了基本的栈操作,如压栈(push)、弹栈(pop)和查看栈顶元素(peek)。以下是Stack类的一些关键源码解析:

类定义与继承

public class Stack<E> extends Vector<E> {// 构造方法public Stack() {super();}// ...
}

压栈 (push)

public E push(E item) {addElement(item); // 直接调用Vector的addElement方法添加元素到数组末尾return item;
}

这里,push方法实际上调用了Vector类的addElement方法,该方法负责在数组的末尾添加一个元素。由于Vector是动态数组,如果数组空间不够,它会自动扩容。

弹栈 (pop)

public synchronized E pop() {E obj;int len = size();obj = peek(); // 获取栈顶元素removeElementAt(len - 1); // 移除最后一个元素,即栈顶元素return obj;
}

pop方法是一个同步方法,确保了线程安全。它首先获取栈顶元素(使用peek方法),然后从Vector中移除该元素。由于removeElementAt方法是线程安全的,所以在多线程环境下这个操作是安全的。

查看栈顶元素 (peek)

public synchronized E peek() {int len = size();if (len == 0)throw new EmptyStackException();return elementAt(len - 1); // 返回最后一个元素,即栈顶元素
}

peek方法同样是线程安全的,用于获取但不移除栈顶元素。如果栈为空,则抛出EmptyStackException

源码解析总结

  • 继承结构Stack类继承自Vector类,这意味着它自动获得了Vector提供的线程安全特性和动态数组的管理能力。Vector 内部维护了一个可自动扩容的数组,当数组空间不足时,会自动进行扩容操作。
  • 压栈 (push):实际上调用了 Vector 的 addElement 方法,该方法在数组末尾添加元素,由于栈的特性是后进先出(LIFO),因此添加在数组末尾正好模拟了这一行为。

弹栈 (pop):首先获取栈顶元素(通过 peek),然后从数组中移除这个元素。由于 Vector 的 removeElementAt 方法会改变数组的长度,从而实现了出栈操作。此方法被声明为 synchronized,确保了多线程环境下的线程安全。

查看栈顶 (peek):不改变栈的状态,仅返回栈顶元素。

  • 同步操作Stack类中的许多操作,特别是修改栈状态的方法(如poppeek),都被声明为synchronized,以确保在多线程环境中的线程安全性。
  • 简单封装Stack类主要是对Vector类提供的方法进行了简单的封装,以符合栈数据结构的LIFO原则。比如,push方法实质上调用了addElement,而pop方法则是组合了获取和移除栈顶元素的操作。

需要注意的是,虽然Stack类提供了方便的栈操作,但在Java集合框架的现代实践中,通常推荐使用Deque接口的实现(如ArrayDeque)作为栈,因为它们提供了更好的性能和灵活性,而不像Stack那样依赖于较为陈旧且同步开销较大的Vector类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/30891.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python | Leetcode Python题解之第155题最小栈

题目&#xff1a; 题解&#xff1a; class MinStack:def __init__(self):self.stack []self.min_stack [math.inf]def push(self, x: int) -> None:self.stack.append(x)self.min_stack.append(min(x, self.min_stack[-1]))def pop(self) -> None:self.stack.pop()sel…

AD域离线破解新思路:Trustroasting和TimeRoasting

简介 近期Tom Tervoort发表了白皮书《TIMEROASTING, TRUSTROASTING AND COMPUTER SPRAYING》并在Github发布了名为Timeroast的工具包&#xff0c;其中介绍了几种新的攻击思路TimeRoasting、Trustroasting和计算机账户密码喷洒&#xff0c;本篇文章主要对TimeRoasting和Trustro…

从零开始:使用ChatGPT快速创作引人入胜的博客内容

随着科技的飞速发展&#xff0c;人工智能逐渐渗透到我们生活的各个领域。无论是商业、教育还是娱乐&#xff0c;AI技术都在以惊人的速度改变着我们。特别是在内容创作领域&#xff0c;人工智能正发挥着越来越重要的作用。今天&#xff0c;我将和大家分享如何从零开始&#xff0…

无约束动态矩阵控制(DMC)

0、前言 动态矩阵控制&#xff08;Dynamic Matrix Control&#xff0c;DMC&#xff09;是一种典型的模型预测控制方法&#xff0c;其不需要被控对象的数学模型&#xff0c;只需要获取被控对象的阶跃响应序列即可实现控制效果&#xff0c;但其需要被控对象是渐近稳定的。 1、稳…

SVN学习(002 svn冲突解决)

尚硅谷SVN高级教程(svn操作详解) 总时长 4:53:00 共72P 此文章包含第20p-第p29的内容 冲突 产生冲突的操作 &#xff08;第一种 相互不影响的操作&#xff09; 用户1修改第二行 用户2修改第四行 用户1提交 用户2提交&#xff0c;提交的时候会提示版本已过时 这时将用…

常见漏洞扫描工具

Fortify Fortify是Micro Focus旗下AST &#xff08;应用程序安全测试&#xff09;产品&#xff0c;其产品组合包括&#xff1a;Fortify Static Code Analyzer提供静态代码分析器&#xff08;SAST&#xff09;&#xff0c;Fortify WebInspect是动态应用安全测试软件&#xff08…

Hadoop 2.0 大家族(一)

目录 一、Hadoop 2.0大家族概述&#xff08;一&#xff09;分布式组件&#xff08;二&#xff09;部署概述 二、ZooKeeper&#xff08;一&#xff09;ZooKeeper简介&#xff08;二&#xff09;ZooKeeper 入门 一、Hadoop 2.0大家族概述 &#xff08;一&#xff09;分布式组件 …

python flask 连接mysql

from flask import Flask, render_template from datetime import datetime from flask_sqlalchemy import SQLAlchemyapp Flask(__name__) # MySQL所在的主机名 HOSTNAME 127.0.0.1 # MySQL监听端口号&#xff0c;默认3306 PORT 3306 # 连接MySQL的用户名 USERNAME root #…

如何使用bt引擎-蚂蚁磁力搜索引擎大全?

bt引擎-蚂蚁磁力链接是一种特殊的下载链接&#xff0c;磁力链接可以理解为一个文件识别码&#xff0c;而并非具体的资源地址&#xff0c;下载软件需要拿着这个识别码去整个互联网(DHT网络)去寻找持有该资源的用户(节点)&#xff0c;如果找到则可以进行传输下载。一般年代越久远…

代码随想录算法训练营DAY43|完全背包、518. 零钱兑换 II、377. 组合总和 Ⅳ、70. 爬楼梯 (进阶)

完全背包 题目链接&#xff1a;完全背包 def material_bag(N, V, weight, value):dp [0] * (V1)for i in range(N):for j in range(weight[i], V1):dp[j]max(dp[j], dp[j-weight[i]]value[i])return dp[V]if __name____main__:N,V map(int, input().split())weight []valu…

不懂索引,简历上都不敢写自己熟悉SQL优化

大家好&#xff0c;我是考哥。 今天给大家带来MySQL索引相关核心知识。对MySQL索引的理解甚至比你掌握SQL优化还重要&#xff0c;索引是优化SQL的前提和基础&#xff0c;我们一步步来先打好地基。 当MySQL表数据量不大时&#xff0c;缺少索引对查询性能的影响不会太大&#x…

用电子表单替代纸质表格,签到报名、出入登记更轻松

用纸质表格收集信息时&#xff0c;常常会出现数据丢失、不易统计等问题。我们可以搭建电子表单来代替线下纸质表格&#xff0c;进行信息收集、记录数据。 这些数据会保存在账号下&#xff0c;可以导出Excel或PDF进行存档&#xff1b;也可以根据企业要求自定义PDF导出格式。 并…

Linux 6.10也引进了蓝屏机制

众所周知&#xff0c;win死机后会有个蓝屏死机的故障提示页面&#xff0c;Linux 6.10 开始也将引入这个机制。 Linux 6.10 引入了一个新的 DRM Panic 处理程序基础设施&#xff0c;以便于在致命错误&#xff08;Panic&#xff09;发生时显示相关信息。 Linux 6.10 还在开发之…

安装oh-my-posh

1、官网地址&#xff1a;https://ohmyposh.dev/docs/installation/windows 2、配置文件如果不存在的话&#xff0c;执行命令 new-item -type file -path $profile -force 3、打开配置文件命令 notepad $PROFILE 4、输入主题 oh-my-posh init pwsh --config C:\Users\77525…

【产品面对面】deepin V23 RC 新体验,文件管理器全面升级!

内容来源&#xff1a;deepin&#xff08;深度&#xff09;社区 在日复一日的数据海洋遨游中&#xff0c;是否曾因文件杂乱无章而苦恼&#xff1f;是否渴望过有一种魔法&#xff0c;能让文件瞬间归位&#xff0c;触手可及&#xff1f; 今天&#xff0c;我们带着全新的文件管理工…

【Pandas驯化-10】一文搞懂Pandas中一列混合多种数据类型to_numeric、select_dtypes处理

【Pandas驯化-10】一文搞懂Pandas中一列混合多种数据类型to_numeric、select_dtypes处理 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; …

中文分词词云图

目录 一、分词1、分词方式方法2、分词优缺点 二、jieba使用示例1、引入库2、切分模式3、加载自定义字典 三、词的可视化1、读取数据2、数据处理3、统计词频4、去除停用词5、词云图1、pyecharts绘图2、WordCloud绘图 一、分词 1、分词方式方法 以构词规则为出发点的规则分词 全…

深入解析PHP函数

PHP函数是一种重要的编程概念&#xff0c;它可以帮助开发者组织和管理代码&#xff0c;提高代码的可重用性和可维护性。在PHP中&#xff0c;函数可以完成各种任务&#xff0c;从简单的数学计算到复杂的数据库查询和数据处理。本文将从多个角度探讨PHP函数的应用&#xff0c;涵盖…

# 消息中间件 RocketMQ 高级功能和源码分析(七)

消息中间件 RocketMQ 高级功能和源码分析&#xff08;七&#xff09; 一、 消息中间件 RocketMQ 源码分析&#xff1a;消息存储核心类介绍 1、消息存储在 store 模块中。消息存储核心类 DefaultMessageStore.java 2、消息存储核心类介绍 private final MessageStoreConfig me…

数据库 | 期末复习专题(HBUT 韩洪木)

总结&#xff1a; 考研数据库系统概论题目整理_若视图的属性来自聚集函数、表达式,则该视图是可以更新的。-CSDN博客 数据库系统概论 ---知识点大全&#xff08;期末复习版&#xff09;_数据库系统概论期末复习-CSDN博客 03数据库关系代数习题_关系代数例题-CSDN博客 【数据库…