全文环境为JDK1.8
本篇目录
1.List 特点2. List 接口的常用方法3.ArrayList 集合4.LinkedList 集合5.Vector 集合
1 - List 特点
List接口继承至Collection接口,存储在List集合中的元素可以重复,且可以为NULL;
与Map集合不同,List集合是有序的,可以像数组一样通过索引来获取元素。
2 - List 接口常用方法
由它的继承关系可以看到List
接口继承至Collection
接口,所以Collection
中有的方法,List
也继承过来了,这里就不讲Collection
的方法了。
// 1-在指定位置插入元素,后面的元素都往后移一个元素
void add(int index, E element)
代码语言:javascript复制// 2-在指定的位置中插入c集合全部的元素,如果集合发生改变,则返回true,否则返回false。
boolean addAll(int index, Collection<? extends E> c)
代码语言:javascript复制// 3-返回list集合中指定索引位置的元素
E get(int index)
代码语言:javascript复制// 4-返回list集合中第一次出现o对象的索引位置,如果list集合中没有o对象,那么就返回-1
int indexOf(Object o)
代码语言:javascript复制// 5-返回此列表元素的列表迭代器(按适当顺序)
ListIterator<E> listIterator()
代码语言:javascript复制// 6-从指定位置开始,返回此列表元素的列表迭代器(按适当顺序)。
ListIterator<E> listIterator(int index)
代码语言:javascript复制// 7-删除指定索引的对象
E remove(int index)
代码语言:javascript复制// 8-在索引为index位置的元素更改为element元素
E set(int index, E element)
代码语言:javascript复制// 9-返回从索引fromIndex到toIndex的元素集合,包左不包右
List<E> subList(int fromIndex, int toIndex)
3 - ArrayList
ArrayList继承关系
毋庸置疑ArrayList
集合是我们最常使用的集合之一,是List
接口的一个实现类。
Cloneable
是一个标记接口,只有实现这个接口后,然后在类中重写clone
方法,然后通过类调用clone
方法才能克隆成功,如果不实现这个接口,则会抛出CloneNotSupportedException
(克隆不被支持)异常。
AbstractList
是一个抽象类,它也实现了List
接口。
那为什么ArrayList
继承它,而不是直接去实现List
接口呢?
这是因为List
的实现类太多了,为了减少这些类的重复代码,所以将它们写成一个抽象类。各位在开发过程中也可以用一下这个思想。
RandomAccess
也是一个标记接口,只有实现这个接口后,就能支持快速随机访问。
往上追溯,可以在Collections
接口中的binarySearch()
方法中会判断当前的List
是否实现了RandomAccess
接口,然后再决定使用for循环
的还是使用迭代器
的形式遍历当前List
。
Serializable
也是一个标记接口,只有实现了这个接口后,这个类才能进行序列化。
ArrayList底层数据结构
代码语言:javascript复制transient Object[] elementData;
从它的源码中可以看到底层是Object[]
,所以它可以存储几乎所有类型的数据。
transient
关键字的作用是在序列化这个对象时,这个属性不会被序列化。
如果对ArrayList
感兴趣可以查看我另一篇对ArrayList
的详解,这篇文章的重心在介绍List
集合。
点击查看-ArrayList深度解析
4 - LinkedList
LinkedList继承关系
Cloneable
和Serializable
上面介绍ArrayList
的时候说过了,这里就不提了。
AbstractSequentialList
抽象类继承至AbstractList
抽象类,而在上面有介绍后者,它俩的区别在前者只支持按次序访问,后者支持随机访问。
这就是为什么LinkedList
集合没有实现RandomAccess
接口,因为它不支持随机访问。
Deque
接口定义了一个双端队列,它提供了一系列针对队列首尾元素的操作方法。
而LinkedList
实现了该接口,意味着它可以做为一个双端队列来使用。
LinkedList底层数据结构
代码语言:javascript复制private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
LinkedList
本质上是一个双向链表,item
存储着本身的元素,next
指向下一个Node
,prev
指向上一个Node
。如下图:
LinkedList 独有的方法
由于LinkedList实现了Deque接口,所以它有Deque接口中的方法。
代码语言:javascript复制// 在集合的头部添加一个元素
void addFirst(E e)
代码语言:javascript复制// 在集合的尾部添加一个元素
void addLast(E e)
代码语言:javascript复制// 获取集合的第一个元素
E getFirst()
代码语言:javascript复制// 获取集合的最后一个元素
E getLast()
代码语言:javascript复制// 删除集合中第一个元素
E removeFirst()
// 删除集合中最后一个元素
E removeLast()
5 - Vector
可以从Vector
的继承关系中看出,它与ArrayList
应该比较相似;
Vector
和ArrayList
的底层数据结构、初始容量、扩容方式等都差不多;
不同的地方是Vector
相对来说是线程安全的,因为它的大多方法都使用synchronized
关键字,如果开发者对线程安全有较高的要求,推荐使用Vector
。
但如果您对线程安全有更高的要求,推荐您使用concurrent
包下的CopyOnWriteArrayList。
对于Vector
的详解,后面我会专门写一篇来介绍。