当前位置: 首页 > news >正文

Vector和ArrayList对比

本文会对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的性能差异已经不明显了。

相关文章:

  • 电商网站域名规则/品牌策划的五个步骤
  • axure做网站下拉菜单/今日新闻内容
  • 做网站哪家好哪家好/新站如何让百度快速收录
  • 怎么做五个页面网站/网络营销seo是什么意思
  • 高密做网站的代理/网站建设明细报价表
  • 温州做网站的公司有哪些/百度百科词条
  • SH-PEG-Silane巯基-聚乙二醇-硅烷试剂简介Silane-PEG-SH
  • Unity 使用OpenXR和XR Interaction Toolkit 开发 HTCVive(Vive Cosmos)
  • 盘点2022年度A站UE神作top
  • docker搭建 nginx+mysql+php-fpm开发环境
  • mybatis之动态SQL常见标签的使用
  • Vue3——第十五章(计算属性:computed)
  • 【IoT】硬件选型:如何正确区分电子线的端子型号?
  • opencv的图像基本操作(基于jupyter Notebook)
  • 【持续更新】VSCode常见快捷键总结
  • Vue知识系列-VS Code的安装+Vue环境的搭建+Vue指令
  • C语言——常用字符串库函数的介绍
  • CentOS 7 升级安装 Python 3.9 版本