8.4.2 ArrayList和Vector实现类
8.4.2 ArrayList和Vector实现类
ArrayList和Vector
ArrayList和Vector作为List类的两个典型实现,完全支持前面介绍的List接口的全部功能。ArrayList和Vector类都是基于数组实现的List类,所以ArrayList和Vector类封装了一个动态的、允许再分配的Object数组。ArrayList或Vector对象使用initialCapacity参数来设置该数组的长度,当向ArrayList或Vector中添加元素超出了该数组的长度时,它们的initialCapacity会自动增加。
使用ensureCapacity方法增加ArrayList容器
对于通常的编程场景,程序员无须关心ArrayList或Vector的initialCapacity。但如果向ArrayList或Vector集合中添加大量元素时,可使用ensureCapacity(int minCapacity)方法一次性地增加initialCapacity。这可以减少重分配的次数,从而提高性能。
如果开始就知道ArrayList或Vector集合需要保存多少个元素,则可以在创建它们时就指定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
如果创建空的ArrayList或Vector集合时不指定initialCapacity参数,则Object数组的长度默认为10。
除此之外, ArrayList和Vector还提供了如下两个方法来重新分配Object数组。
| 方法 | 描述 |
|---|---|
void ensureCapacity(int minCapacity) |
将ArrayList或Vector集合的Object数组长度增加大于或等于minCapacity值。 |
void trimToSize() |
调整ArrayList或Vector集合的Object数组长度为当前元素的个数。调用该方法可减少ArrayList或 Vector集合对象占用的存储空间. |
尽量不要用Vector
ArrayList和Vector在用法上几乎完全相同,但由于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线程安全
除此之外, ArrayList和Vector的显著区别是: 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