ArrayList和Vector有什么区别?

413
ArrayListVector这两种数据结构有哪些区别,它们各自适用的场景是什么?

6
我在这里没有看到完全相同的副本。 - Jeff Atwood
2
嗯,你也可以在Java中创建向量 -Vector v = new Vector(3, 2); - sgsi
永远不要使用 Vector,请使用 ArrayListLinkedList 或者 ArrayDeque - user8389458
7个回答

427

差异

  • 向量(Vector)是同步的,而ArrayList则不是。
  • 数据增长方法

如果没有特殊要求使用向量(Vector),则使用ArrayList。

同步

如果多个线程同时访问ArrayList,则必须对修改列表的代码块进行外部同步,无论是结构上修改列表还是简单地修改元素。结构修改指添加或删除一个或多个元素到列表中。设置现有元素的值不属于结构性修改。

通常在创建列表时使用Collections.synchronizedList以避免意外的非同步访问。

数据增长

在内部,ArrayList和Vector都使用数组来保存其内容。当将元素插入ArrayList或Vector时,如果它们的内部数组已经满了,则对象需要扩展其内部数组。向量默认情况下将其数组大小加倍,而ArrayList将其数组大小增加50%。


9
@Rei 他所说的就是:_多线程_(https://docs.oracle.com/javase/tutorial/essential/concurrency/index.html) - RecursiveExceptionException
1
从ArrayList中以多线程方式读取呢?那是线程安全的吗? - Xunie
2
@Xunie 从ArrayList或其他集合类中读取数据通常不是问题。问题出现在向ArrayList或集合添加、删除或修改现有值的时候。 - sainath reddy
这里底部给出的参考链接已经过时并且会导致垃圾邮件。 - Gonen I
有谁能为“向量”这个名称提出合理的解释吗?因为在物理学中,“向量”有完全不同的意义。但在数学中,他们说向量是一行数据。 - Sreekanth Karumanaghat
在这里使用向量(vector)的原因几乎有99%是因为C++中的arraylist被称为vector。关于这点,你可以查看这个线程:https://dev59.com/NHRB5IYBdhLWcg3wl4EP - EricChen1248

101
正如文档所述,VectorArrayList几乎等同。区别在于对Vector的访问是同步的,而对ArrayList的访问则不是。这意味着只有一个线程可以同时调用Vector上的方法,并且在获取锁时会有轻微的开销;如果你使用ArrayList,那么就不会有这个问题。通常情况下,你会想使用ArrayList;在单线程情况下,它是更好的选择,在多线程情况下,你可以更好地控制锁定。想允许并发读取?可以。想为十次写操作执行一次同步?也可以。这需要你稍微费些心思,但这很可能是你想要的。此外,请注意,如果你拥有一个ArrayList,你可以使用Collections.synchronizedList函数创建一个同步列表,这样就可以获得一个Vector的等效对象。

69

Vector 是一个破损的类,尽管它被“同步”,但它不是线程安全的,只适用于学生和其他经验不足的程序员。

ArrayList 是专业人士和有经验的程序员使用的首选列表实现。

想要线程安全的列表实现的专业人士使用CopyOnWriteArrayList


18
同步但不线程安全?这是什么意思?【我是初学者】 - Dineshkumar
18
@Dineshkumar Vector本意是线程安全的,但存在设计缺陷使其实际上并非线程安全,它基本上已成为一个废弃的类。出于某种原因,一些大学等机构还没有听说过这个消息,并仍然倡导使用它。 - Bohemian
5
@Dineshkumar 抱歉 - 那个链接不太好,这里是定义性答案。简而言之,它的同步功能是无用的。 - Bohemian
2
@AdrianShum Collections.synchronizedList() 是低效的,而且已经被淘汰。根据 javadoc 的说明,客户端必须手动同步返回的列表以安全地进行迭代:虽然是线程安全的,但多个线程不能同时安全地迭代,这使它成为一种残酷、不可扩展的解决方案。它的使用已被 java.util.concurrent 类取代。 - Bohemian
10
有趣的事实:Java1.7的堆栈使用了Vector类。 - Tobi
显示剩余3条评论

29

ArrayList 是较新的数据结构,速度比 Vector 快 20-30%。

如果你不需要 Vector 特有的功能,可以使用 ArrayList


37
你能否提供证据支持声称“比原来快20-30%”? - user
6
@user 当时只是从处理大型数组的个人经验中得出结论。现在已经过去三年了,我无法准确指出当时所讨论的内容,但是有很多基准测试可供参考。只有在使用线程时才能看到最大的性能提升,但这里有一个例子:http://www.javacodegeeks.com/2010/08/java-best-practices-vector-arraylist.html - Oli
1
只有20-30%的匹配度,如果您同时读写Vector/Arraylist,因为增长函数将产生最大的影响。如果您有一个基准测试仅写入一次,然后执行仅读取操作,将会得到不同的结果。 - Tobi
3
请提供证据支持你的数据。 - wiredmark
1
由于向量是同步的而ArrayList不是同步的,这可能是ArrayList比向量更快的原因。 - ASK

28

Vector和ArrayList有2个主要区别:

  1. Vector默认是同步的,而ArrayList不是。 注意:你可以通过将arraylist对象传递给Collections.synchronizedList()方法来使ArrayList也变成同步的。同步意味着:它可以与多个线程一起使用,没有任何副作用。

  2. 当空间不足以容纳新元素时,ArrayList的大小增长了前一个大小的50%,而Vector将增长前一个大小的100%。

除此之外,在编程方面还存在一些实际差异:

  1. 要从Vector中获取特定位置的元素,我们使用elementAt(int index)函数。这个函数名很长。 相比之下,在ArrayList中我们有get(int index),这非常易于记忆和使用。
  2. 同样地,在Vector中用新元素替换现有元素,我们使用setElementAt()方法,这又是非常长的,可能会让程序员反复使用感到烦恼。相比之下,ArrayList具有add(int index, object)方法,易于使用和记忆。 像这样,它们在ArrayList中有更加友好和易于使用的函数名。

何时使用哪个?

  1. 尽量完全避免使用Vectors。ArrayLists可以做到所有Vector能做的事情。而且ArrayLists默认不同步。如果需要,可以使用Collections util类在需要时进行同步。
  2. ArrayList具有易于记忆和使用的函数名称。

注意:即使ArrayList增长了100%,您也可以通过ensurecapacity()方法避免这种情况,以确保在最初阶段分配足够的内存。

希望能对你有所帮助。


5
ArrayList和Vector的增长大小信息错误(被交换),除此之外回答得相当不错。 - Nenad Bulatović
1
Vector的增长速度是需要的,而且会翻倍。具体请参考http://docs.oracle.com/javase/7/docs/api/java/util/Vector.html。ArrayList的增长策略没有具体说明,只知道添加元素的时间成本是恒定的分摊时间成本。具体请参考http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html。 - Mohamed ElNakeep
我不理解方法名如何成为使用或不使用该方法的标准。 - Surender Khairwa

19

ArrayListVector都实现了List接口并保持插入顺序。但是ArrayListVector类之间有很多区别...

ArrayList -

  1. ArrayList是非同步的。
  2. 如果元素数量超过容量,ArrayList会将当前数组大小增加50%。
  3. ArrayList不是遗留类,它是在JDK 1.2中引入的。
  4. ArrayList快速,因为它是非同步的。
  5. ArrayList使用Iterator接口来遍历元素。

Vector -

  1. Vector是同步的。
  2. 如果总元素数超过容量,Vector会将数组大小增加100%,即翻倍。
  3. Vector是一个遗留类。

  4. Vector慢,因为它是同步的,即在多线程环境中,它将保持其他线程处于可运行或不可运行状态,直到当前线程释放对象的锁。

  5. Vector使用Enumeration接口来遍历元素。但它也可以使用Iterator。

参见:https://www.javatpoint.com/difference-between-arraylist-and-vector


10
基本上,ArrayList和Vector都使用内部对象数组。
ArrayList:ArrayList类扩展了AbstractList并实现了List接口和RandomAccess(标记接口)。ArrayList支持动态数组,可以根据需要增长。它允许我们首次迭代元素。 ArrayList使用内部对象Array;它们的默认初始大小为10。当超出此大小时,集合会自动增加到默认大小的一半,即15。
Vector:Vector与ArrayList类似,但差异在于它是同步的,其默认初始大小为10,当大小超过其大小时,其大小增加到原始大小的两倍,这意味着新大小将为20. Vector是仅有的另一个实现RandomAccess的类,Vector有四个构造函数,其中一个采用两个参数Vector(int initialCapacity,int capacityIncrement) ,capacityIncrement是向量溢出时要增加的容量量,因此它对负载因子具有更多控制。
一些其他区别如下图所示:enter image description here

1
为什么在LinkedList的开头和结尾添加对象很慢?难道它不应该比ArrayList和Vector都要快吗? - CHANist
@CHANist 我也同意。在开头和结尾添加对象应该比在中间添加对象更快。 - Rahul Rastogi
1
这个表中LinkedList列使用的语言是自相矛盾的。在LinkedList中,前置和后置添加元素比在中间添加元素更快,但比在ArrayList或Vector中前置或后置添加要慢。这是因为每次插入都需要进行内存分配,并且其中包含非本地引用,从而增加了缓存未命中的机会。尽管LinkedList中查找是与元素数量成线性关系的,且没有指向末尾的指针,但追加仍然比前置要快,因为只有一个元素需要重新分配内存。 - Sophia Gold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接