Vector和ArrayList对比

news2025/1/12 6:18:06

本文会对ArrayListVector进行分析,为什么会关注这两个类,主要是因为他们拥有相同的继承结构,接下来就来探索下这两个类实现和效率的异同。

继承结构

可以看到,VectorArrayList都实现了ListRandomAccess接口,都继承了AbstractList。通过他们的继承结构,大致可以猜测他们在元素的处理上存在很多相同的地方。

存储结构

VectorArrayList都使用 Object [] elementData保存数据,但是不同的ArrayListelementData使用transient做了标记,这说明ArrayListelementData不参与对象序列化的过程。

添加元素

  • Vectoradd(E)``add(int, E)``addElement(E obj)``addAll(Collection<? extends E> c)``addAll(int, Collection<? extends E> c)``insertElementAt(E obj, int )
  • ArrayListadd(E)``add(int, E)``addAll(Collection<? extends E> c)``addAll(int, Collection<? extends E> c)在元素的添加上,VectorArrayList差不多提供了相同的接口,但是最大的不同是Vector提供的接口中,除了add(int, E)之外,都是同步接口,但是add(int, E)最终会调用同步方法insertElementAt(E obj, int ),故Vector添加元素都是同步方法;ArrayList添加元素的方法都是非同步方法。

访问

  • Vectorget(int index)``elementAt(int index)* ArrayListget(int index)在对元素的随机访问上,VectorArrayList多了一个elementAt(int index)函数,但是elementAt(int index)get(int index)原理是一样的,故可以总结为VectorArrayList在随机访问元素时实现了同样的接口。最大的不同仍然是Vector对元素的随机访问是同步的,而ArrayList是非同步的。

遍历

ArrayList提供了foreach, Iterator的遍历方式,Vector除此之外还提供了另外两种遍历方式:

 Vector<String> sVector = new Vector<>();for (int i = 0 ; i < 5 ; i++) {
		sVector.add("test" + i);
	}
	
	sVector.forEach(new Consumer<String>() {
		@Override
		public void accept(String t) {
			// TODO Auto-generated method stub
			System.out.println(t);	
		}
	});
		
		
	Enumeration<String> enumeration = sVector.elements();
	while (enumeration.hasMoreElements()) {
		System.out.println(enumeration.nextElement());
	} 

Vector中,这两种方式和使用Iterator方式遍历最大的区别是他们不是同步的,主要原因是以上两种遍历方法不会在遍历过程中对集合中的数据进行修改。

扩容

由于使用数组存储元素,在元素不断的增加程中,VectorArrayList都需要对数组容量进行增加,在数组容量变化上,VectorArrayList选择了不一样的策略。

  • Vector```
    private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?capacityIncrement : oldCapacity);

    }

在扩容的时候,如果`capacityIncrement > 0`(`caoaciryIncrement`是新建`Vector`时传递的第二个参数,但是在具体使用很少使用这个参数,故大多数情况下`capacityIncrement=0`),则将容量增加`capacityIncrement`,否则容量直接增加一倍。

* ArrayList```
 private void grow(int minCapacity) {
		// overflow-conscious code
		int oldCapacity = elementData.length;
		int newCapacity = oldCapacity + (oldCapacity >> 1);
		......
	} 

ArrayList的扩容很简单,直接在原来容量的基础上增加了50%。

效率究竟差多少

Vector是线程安全的容器,它的很多方法都使用synchronzied方法进行了修饰,说明要使用Vector实例,需要先获得锁,这一过程比较耗时,但是究竟能耗时多少,是不是比ArrayList耗时很多?本文不打算去测试在多线程环境下两者的对比,因为在使用ArrayList的时候,大多数场景是单线程的环境,本文就在单线程的环境中对VectorArrayList进行对比,这种对比不是精确的对比,只是对比一下快慢。本文从添加,遍历和随机访问三个方面进行对比。测量的方法比较简单,就是先向集合中添加元素,然后再去遍历元素,最后分别统计添加元素,遍历元素和随机访问的耗时,测试的java环境是jdk1.8.0_181。* Vector

 long start = System.currentTimeMillis();
	for (int i = 0 ; i < 500000 ; i++) {
		sVector.add("qiwoo_test_add" + i);
	}
	long end = System.currentTimeMillis();
	System.out.println("vector add time consuming:" + (end - start));

	Iterator<String> iterator = sVector.iterator();
	long visitStart = System.currentTimeMillis();
	while (iterator.hasNext()) {
		String str = iterator.next();
	}
	long visitEnd = System.currentTimeMillis();
	System.out.println("vector visit time consuming:" + (visitEnd -visitStart));
		
	long randAccessStart = System.currentTimeMillis();
	for (int i = 0 ; i < 500000 ; i++) {
		sVector.get(i);
	}
	long randAccessend = System.currentTimeMillis();
	System.out.println("vector random access time consuming:" +(randAccessend - randAccessStart)); 

在我的电脑上,运行的结果如下:vector add time consuming:95vector visit time consuming:18vector random access time consuming:14* ArrayList

 long start = System.currentTimeMillis();
	for (int i = 0 ; i < 500000 ; i++) {
		sArray.add("qiwoo_test_add" + i);
	}
	long end = System.currentTimeMillis();
	System.out.println("array add time consuming:" + (end - start));
	
	
	
	Iterator<String> iterator = sArray.iterator();
	long visitStart = System.currentTimeMillis();
	while (iterator.hasNext()) {
		String str = iterator.next();
	}
	long visitEnd = System.currentTimeMillis();
	System.out.println("array visit time consuming:" + (visitEnd -visitStart));
	
	long randAccessStart = System.currentTimeMillis();
	for (int i = 0 ; i < 500000 ; i++) {
		sArray.get(i);
	}
	long randAccessend = System.currentTimeMillis();
	System.out.println("array random access time consuming:" +(randAccessend - randAccessStart)); 

在我的电脑上运行结果如下:array add time consuming:82array visit time consuming:11array random access time consuming:5上面的结果可以发现,在单线程环境下,在元素添加和遍历上,Vector均比ArrayList慢了一些,其中添加元素慢了8%左右,遍历元素慢了64%,随机访问慢了1.8倍,这些数据可能受数据量的不同而不同,但是整体的趋势应该是一致的。以上测试的时候,数据量为500000,但是实际进行Android开发的过程中产生的数据量比较少,参考下google设计容器时的数量考虑,接下来把数据量设置为1000,看下运行结果的差异

  • Vectorvector add time consuming:2vector visit time consuming:1array random access time consuming:0* ArrayListarray add time consuming:2array visit time consuming:1array random access time consuming:0当数据量到1000时,VectorArrayList在元素的添加,遍历和随机访问上已经没有什么性能差异或者说差异很小。

总结

ArrayListVector都是java中比较重要的容器,他们都可以存储各种对象,它们有相同的继承结构,提供大致相同的功能,主要的差异点如下:

  • Vector是线程安全的容易,可以在并发环境中安全地使用,而ArrayList是非线程安全的
  • ArrayList进行扩容时增加50%,Vector提供了扩容时的增量设置,但通常将容量扩大1倍
  • Vector可以使用Enumeration和Iterator进行元素遍历,ArrayList只提供了Iterator的方式
  • 由于使用的线程同步,Vector的效率比ArrayList

自java1.6之后,为了优化synchronized,java引入了偏向锁,在单线程环境中,Vector的效率已经被提高了。从刚才的对比也可以发现,在单线程环境中,数据量较少(测试数据量在100000性能差异较小)的情况下,VectorArrayList的性能差异已经不明显了。

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

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

相关文章

C语言——常用字符串库函数的介绍

文章目录常用字符串库函数介绍1.1关于字符串简介1.2:[strlen库函数](https://legacy.cplusplus.com/reference/cstring/strlen/?kwstrlen)1.2.1strlen函数的功能1.2.2strlen函数的参数和返回类型1.2.3strlen函数使用注意事项1.2.4strlen的使用1.2.5模拟实现strlen函数1.3:[str…

喜讯!酷开科技荣获中国国际广告节三项殊荣!

近日&#xff0c;由中国广告协会主办的第29届中国国际广告节AD Fair媒企交易会在厦门国际会展中心隆重举行。其中备受瞩目的三大盛典&#xff1a;广告主金伙伴盛典、广告主盛典、媒企盛典&#xff0c;是广告业必不可少的荣誉殿堂&#xff0c;他们不仅是对中国广告传媒业各方主体…

【C++升级之路】第七篇:STL简介

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;从整体上对STL进行粗略介绍 &#x1f6a2;&#x1f6a2;作者简介&#xff1a;计算机海洋的新进船长一枚&…

GTD之初总结

思维导图 GTD&#xff1a;GTD是“Getting Things Done”的缩写&#xff0c;是由效率管理专家戴维艾伦&#xff08;David Allen&#xff09;开创的一套完整个人时间管理系统 既高效地处理工作事务&#xff0c;又能品味生活的快乐滋味&#xff0c;达到心如止水的轻松感 GTD工作…

docker中基础内容

docker中的核心概念 1、镜像&#xff1a; Image 定义&#xff1a;一个镜像就代表一个软件&#xff0c;比如&#xff1a;mysql 镜像、redis 镜像、es镜像等等2、容器&#xff1a; Container 定义&#xff1a;一个镜像运行一次就会生成一个容器&#xff0c;容器就是一个运行的软…

托普云农在创业板IPO过会:拟募资约3亿元,前三季度利润下滑8%

近日&#xff0c;深圳证券交易所披露的信息显示&#xff0c;浙江托普云农科技股份有限公司&#xff08;下称“托普云农”&#xff09;获得创业板上市委会议通过。据贝多财经了解&#xff0c;托普云农于2022年6月24日递交招股书并获得受理。 本次冲刺创业板上市&#xff0c;托普…

分享36个C源码,总有一款适合您

C源码 分享36个C源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c;大家下载后可以看到。 源码下载链接&#xff1a;https://pan.baidu.com/s/1WTLgtQ2J5gfZdj-LMEYnEA?pwdnimr 提取码…

Swagger使用

SpringBoot继承Swagger <!--swagger依赖--> <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version> </dependency> <!--swagger ui--> <dependen…

列表元素的查找,插入和删除

1&#xff0c;查找列表元素&#xff1a; 语法格式&#xff1a;ls.index(x) 其中&#xff0c;ls是要进行元素查找操作对象&#xff0c;x为要查元素值&#xff0c;返回值是ls中第一个值为x的元素的位置。例如&#xff1a;ls[1,2,3,6]#创建一个列表 print&#xff08;ls值为6的元…

Linux操作系统进程状态Linux内核进程状态

目录 Linux操作系统进程状态 1. 新建 2. 运行 3. 阻塞 4. 挂起 Linux内核进程状态 进程状态查看 Linux操作系统进程状态 1. 新建 即字面意思&#xff0c;将进程资源(PCB)加载到内存,运行状态之前就是新建。 2. 运行 进程正在运行或者task_struct 结构体在队列中排队&…

leetcode 1813. 句子相似性 III【python3双指针的实现思路及过程整理】

题目 一个句子是由一些单词与它们之间的单个空格组成&#xff0c;且句子的开头和结尾没有多余空格。比方说&#xff0c;“Hello World”&#xff0c;“HELLO”&#xff0c;"hello world hello world"都是句子。每个单词都只包含大写和小写英文字母。 如果两个句子 s…

【数据结构】图的案例引入及类型定义

6.2 案例引入 六度空间理论 六度空间理论验证 6.3 图的类型定义 图的抽象数据类型定义如下 ADT Graph {数据对象V&#xff1a;具有相同特性的数据元素的集合&#xff0c;称为顶点集。数据关系R&#xff1a;R{VR}VR{<v,w>|<v,w>|v,w∈V ^ p(v,w),<v,w>表述…

WebStorage之浏览器的本地存储(结合案例)

目录前言一&#xff0c;WebStorage二&#xff0c;localStorage2.1 存储2.2 读取2.3 删除2.4 清除全部2.5 代码三&#xff0c;sessionStorage3.1 用法3.2 区别3.3 代码四&#xff0c;结合案例后记前言 浏览器的本地存储可以缓存一些信息在浏览器中&#xff0c;方便取用。在学习…

Docker(黑马spring cloud笔记)

Docker 目录Docker一、介绍和安装1. 安装2. 启动3. 镜像加速二、Docker基本操作1. 镜像操作2. 容器操作3. 数据卷操作三、Dockerfile1. 镜像结构2. Dockerfile四、Docker-Compose1. 安装2. 基本命令五、Docker私服搭建六、练习练习1&#xff1a;save和load练习2&#xff1a;doc…

【MySQL】深入学习B+索引的使用

文章目录1. 前言2. 索引的代价2.1 空间上的代价2.2 时间上的代价3. B树索引的使用3.1 提取正确的扫描区间3.1.1 所有搜索条件都可以生成合适的扫描区间的情况3.1.2 有的搜索搜索条件不能生成合适的扫描区间3.1.3 从复杂的搜索条件中找出扫描区间3.1.4 使用联合索引执行查询时对…

5. 统计学基础2:协方差、相关系数、协方差矩阵

文章目录1. 协方差2. 相关系数【就是使 |协方差|<1】3. 协方差矩阵1. 协方差 标准差和方差一般是用来描述一维数据的&#xff0c; 具体介绍见&#xff1a;5. 统计学基础1&#xff1a;平均值…四分位数、方差、标准差&#xff08;均方差&#xff09;、标准误&#xff08;标准…

ModelMapper 一文读懂

目录 1、ModelMapper简介 1.1 引入ModelMapper 的依赖 1.2 进行Mapping映射 1.3 ModelMapper 工作原理 2、ModelMapper 基础操作 2.1 ModelMapper 基本映射 2.2 ModelMapper 集合转换 2.3 ModelMapper 指定默认值 2.4 ModelMapper 属性值转换 2.5 ModelMapper 属…

node.js创建服务器及知识点

node.js创建服务器及知识点用http协议创建web服务器http协议知识点用express创建web服务器express中路由知识点fs文件系统模块文件流querystring查询字符串模块URL模块中间件挂载路由器node.js和mysql项目实战知识点完整代码注意点用http协议创建web服务器 //引入http const h…

【强训】Day07

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录一、选择二、编程1. Fibonacci数列2. 合法括号序列判断 ☆答案1. 选择2. 编程普通小孩也要热爱生活&#xff01; 一、选择 Math.round(11.5) 等于&#xff08;&#xff09; A 11 B 11.5 C 12 D 12.5 以下对继承的描…

Spring Boot(五十四):SpringBoot事件监听机制

1 Java监听机制 SpringBoot 的监听机制&#xff0c;其实是对Java提供的事件监听机制的封装。 Java中的事件监听机制定义了以下几个角色&#xff1a; 事件&#xff1a;Event&#xff0c;继承 java.util.EventObject 类的对象事件源&#xff1a;Source &#xff0c;任意对象Ob…