(1) void add(Object o): 将对象o添加到当前位置的前面
void set(Object o): 用对象o替代next或previous方法访问的上一个元素。如果上次调用后列表结构被修改了,那么将抛出IllegalStateException异常。
(2) boolean hasPrevious(): 判断向后迭代时是否有元素可访问
Object previous():返回上一个对象
int nextIndex(): 返回下次调用next方法时将返回的元素的索引
int previousIndex(): 返回下次调用previous方法时将返回的元素的索引
3.2 抽象类AbstractList和AbstractSequentialList
有两个抽象的 List 实现类:AbstractList 和 AbstractSequentialList。像 AbstractSet 类一样,它们覆盖了 equals() 和 hashCode() 方法以确保两个相等的集合返回相同的哈希码。若两个列表大小相等且包含顺序相同的相同元素,则这两个列表相等。这里的 hashCode() 实现在 List 接口定义中指定,而在这里实现。
除了equals()和hashCode(),AbstractList和AbstractSequentialList实现了其余 List 方法的一部分。因为数据的随机访问和顺序访问是分别实现的,使得具体列表实现的创建更为容易。需要定义的一套方法取决于您希望支持的行为。您永远不必亲自提供的是 iterator方法的实现。
3.3 类LinkedList、ArrayList和Vector
在“集合框架”中有两种常规的 List 实现:ArrayList 和 LinkedList。使用两种 List 实现的哪一种取决于您特定的需要。如果要支持随机访问,而不必在除尾部的任何位置插入或除去元素,那么,ArrayList 提供了可选的集合。但如果,您要频繁的从列表的中间位置添加和除去元素,而只要顺序的访问列表元素,那么,LinkedList 实现更好。
ArrayList 和 LinkedList 都实现 Cloneable 接口,都提供了两个构造函数,一个无参的,一个接受另一个Collection
3.1.1 类LinkedList
LinkedList类添加了一些处理列表两端元素的方法。
(1) void addFirst(Object o): 将对象o添加到列表的开头
void addLast(Object o):将对象o添加到列表的结尾
(2) Object getFirst(): 返回列表开头的元素
Object getLast(): 返回列表结尾的元素
(3) Object removeFirst(): 删除并且返回列表开头的元素
Object removeLast():删除并且返回列表结尾的元素
(4) LinkedList(): 构建一个空的链接列表
使用这些新方法,您就可以轻松的把 LinkedList 当作一个堆栈、队列或其它面向端点的数据结构。
3.1.2 类ArrayList
ArrayList类封装了一个动态再分配的Object[]数组。每个ArrayList对象有一个capacity。这个capacity表示存储列表中元素的数组的容量。当元素添加到ArrayList时,它的capacity在常量时间内自动增加。
在向一个ArrayList对象添加大量元素的程序中,可使用ensureCapacity方法增加capacity。这可以减少增加重分配的数量。
(1) void ensureCapacity(int minCapacity): 将ArrayList对象容量增加minCapacity
(2) void trimToSize(): 整理ArrayList对象容量为列表当前大小。程序可使用这个操作减少ArrayList对象存储空间。
3.1.3 类Vector
Vector类似于ArrayList。从API的角度来看这两个类非常相似。Vector是同步的,这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是异步的,因此ArrayList中的对象并不是线程安全的。
3.1.4 三者之间的区别
3.1.4.1 LinkedList与ArrayList的区别
ArrayList:支持随机访问,不必在除尾部的任何位置插入或除去元素。
LinkedList:频繁的从列表的中间位置添加和除去元素,而只要顺序的访问列表元素。
3.1.4.2 Vector与ArrayList的区别
(1) 同步性
Vector是同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是异步的,因此ArrayList中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销。
(2) 数据增长
从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。
(3) 使用模式
在ArrayList和Vector中,从一个指定的位置(通过索引)查找数据或是在集合的末尾增加、移除一个元素所花费的时间是一样的,这个时间我们用O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除元素的索引位置。为什么会这样呢?以为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行位移的操作。这一切意味着什么呢?
这意味着,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作,你最好选择其他的集合操作类。比如,LinkList集合类在增加或移除集合中任何位置的元素所花费的时间都是一样的—O(1),但它在索引一个元素的使用却比较慢-O(i),其中i是索引的位置。使用ArrayList也很容易,因为你可以简单的使用索引来代替创建iterator对象的操作。LinkList也会为每个插入的元素创建对象,所有你要明白它也会带来额外的开销。
最后,在《Practical Java》一书中Peter Haggar建议使用一个简单的数组(Array)来代替Vector或ArrayList。尤其是对于执行