8.4.2 ArrayList和Vector实现类

8.4.2 ArrayList和Vector实现类

ArrayList和Vector

ArrayListVector作为List类的两个典型实现,完全支持前面介绍的List接口的全部功能。
ArrayListVector类都是基于数组实现的List,所以ArrayListVector类封装了一个动态的、允许再分配的Object数组。
ArrayListVector对象使用initialCapacity参数来设置该数组的长度,当向ArrayListVector中添加元素超出了该数组的长度时,它们的initialCapacity会自动增加。

使用ensureCapacity方法增加ArrayList容器

对于通常的编程场景,程序员无须关心ArrayListVectorinitialCapacity。但如果向ArrayListVector集合中添加大量元素时,可使用ensureCapacity(int minCapacity)方法一次性地增加initialCapacity。这可以减少重分配的次数,从而提高性能。

如果开始就知道ArrayListVector集合需要保存多少个元素,则可以在创建它们时就指定initialCapacity大小。

方法 描述
ArrayList(int initialCapacity) Constructs an empty list with the specified initial capacity.
方法 描述
Vector(int initialCapacity) Constructs an empty vector with the specified initial capacity and with its capacity increment equal to zero.

ArrayList或Vector默认容量为10

如果创建空的ArrayListVector集合时不指定initialCapacity参数,则Object数组的长度默认为10

除此之外, ArrayListVector还提供了如下两个方法来重新分配Object数组。

方法 描述
void ensureCapacity(int minCapacity) ArrayListVector集合的Object数组长度增加大于或等于minCapacity值。
void trimToSize() 调整ArrayListVector集合的Object数组长度为当前元素的个数。调用该方法可减少ArrayListVector集合对象占用的存储空间.

尽量不要用Vector

ArrayListVector在用法上几乎完全相同,但由于Vector是一个古老的集合(从JDK 1.0就有了),那时候Java还没有提供系统的集合框架,所以Vector里提供了一些方法名很长的方法,例如addElement(Object obj),实际上这个方法与add(Object obj)没有任何区别。从JDK1.2以后,Java提供了系统的集合框架,就将Vector改为List接口实现之一了,从而导致Vector里有一些功能重复的方法。
Vector的系列方法中方法名更短的方法属于后来新增的方法,方法名更长的方法则是Vector原有的方法。Java改写了Vector原有的方法,将其方法名缩短是为了简化编程。而ArrayList开始就作为List接口的主要实现类,因此没有那些方法名很长的方法。实际上, Vector具有很多缺点,通常**尽量少用Vector**这个实现类。

ArrayList线程不安全 Vector线程安全

除此之外, ArrayListVector的显著区别是: ArrayList是线程不安全的,当多个线程访问同一个ArrayList集合时,如果有超过一个线程修改了ArrayList集合,则程序必须手动保证该集合的同步性;
但**Vector集合则是线程安全的**,无须程序保证该集合的同步性。因为Vector是线程安全的,所以Vector的性能比ArrayList的性能要低。实际上,即使需要保证List集合线程安全,也同样不推荐使用Vector这个实现类。后面会介绍一个**Collections工具类,它可以将一个ArrayList变成线程安全的**。

Stack类

Vector还提供了一个Stack子类,它用于模拟”栈”这种数据结构,”栈”通常是指”后进先出“(LIFO)的容器。最后”push“进栈的元素,将最先被”pop“出栈。与Java中的其他集合一样,进栈出栈的都是Object,因此从栈中取出元素后必须进行类型转换,除非你只是使用Object具有的操作。

Stack类方法

方法 描述
E peek() 返回”栈”的第一个元素,但并不将该元素”pop“出栈。
E pop() 返回“栈”的第一个元素,并将该元素“pop”出栈。
E push(E item) 将一个元素”push“进栈,最后一个进”栈”的元素总是位于”栈”顶。
boolean empty() Tests if this stack is empty.
int search(Object o) Returns the 1-based position where an object is on this stack.

尽量少用Stack

需要指出的是,由于Stack继承了Vector,因此它也是一个非常古老的Java集合类,Stack同样是线程安全、性能较差的,因此应该尽量少用Stack类。如果程序需要使用”栈”这种数据结构,则可以考虑使用后面将要介绍的ArrayDeque

ArrayDeque

ArrayDeque也是List的实现类, ArrayDeque既实现了List接口,也实现了Deque接口,由于实现了Deque接口,因此可以作为栈来使用;而且ArrayDeque底层也是基于数组的实现,因此性能也很好。本书将在8.5节详细介绍ArrayDeque