8.4.2 ArrayList和Vector实现类
ArrayList和Vector作为List类的两个典型实现,完全支持前面介绍的List接口的全部功能。ArrayList和Vector类都是基于数组实现的List类,所以ArrayList和Vector类封装了一个动态的、允许再分配的Object数组。 ArrayList或Vector对象使用initialCapacity参数来设置该数组的长度,当向ArrayList或Vector中添加元素超出了该数组的长度时,它们的initialCapacity会自动增加。
对于通常的编程场景,程序员无须关心ArrayList或Vector的initialCapacity。但如果向ArrayList或Vector集合中添加大量元素时,可使用ensureCapacity(int minCapacity)方法一次性地增加initialCapacity。这可以减少重分配的次数,从而提高性能。
如果开始就知道ArrayList或Vector集合需要保存多少个元素,则可以在创建它们时就指定initialCapacity大小。如果创建空的ArrayList或Vector集合时不指定initialCapacity参数,则Object数组的长度默认为10。
除此之外, ArrayList和Vector还提供了如下两个方法来重新分配Object数组。
| 方法 | 描述 | 
|---|---|
| void ensureCapacity(int minCapacity) | 将 ArrayList或Vector集合的Object数组长度增加大于或等于minCapacity值。 | 
| void trimToSize() | 调整 ArrayList或Vector集合的Object数组长度为当前元素的个数。调用该方法可减少ArrayList或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是线程不安全的,当多个线程访问同一个ArrayList集合时,如果有超过一个线程修改了ArrayList集合,则程序必须手动保证该集合的同步性; | |
| 但 Vector集合则是线程安全的,无须程序保证该集合的同步性。因为Vector是线程安全的,所以Vector的性能比ArrayList的性能要低。实际上,即使需要保证List集合线程安全,也同样不推荐使用Vector这个实现类。后面会介绍一个Collections工具类,它可以将一个ArrayList变成线程安全的。 | |
| Vector还提供了一个Stack子类,它用于模拟”栈”这种数据结构,”栈”通常是指”后进先出“(LIFO)的容器。最后”push“进栈的元素,将最先被”pop“出栈。与Java中的其他集合一样,进栈出栈的都是Object,因此从栈中取出元素后必须进行类型转换,除非你只是使用Object具有的操作。所以Stack类里提供了如下几个方法 | 
| 方法 | 描述 | 
|---|---|
| Object peek() | 返回”栈”的第一个元素,但并不将该元素” pop“出栈。 | 
| Object pop() | 返回“栈”的第一个元素,并将该元素“ pop”出栈。 | 
| void push(Object item) | 将一个元素” push“进栈,最后一个进”栈”的元素总是位于”栈”顶。 | 
| 需要指出的是,由于 Stack继承了Vector,因此它也是一个非常古老的Java集合类,Stack同样是线程安全的、性能较差的,因此应该尽量少用Stack类。如果程序需要使用”栈”这种数据结构,则可以考虑使用后面将要介绍的ArrayDeque | 
ArrayDeque也是List的实现类, ArrayDeque既实现了List接口,也实现了Deque接口,由于实现了Deque接口,因此可以作为栈来使用;而且ArrayDeque底层也是基于数组的实现,因此性能也很好。本书将在8.5节详细介绍ArrayDeque