List接口扩展了Collection并声明存储一系列元素的类集的特性,使用一个基于零的下标,元素可以通过它们在列表中的位置被插入和访问。
List是有序、可重复的容器。
有序:List中每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问元素,从而精确控制这些元素。
可重复:List允许加入重复的元素。更确切地讲,List通常允许满足 e1.equals(e2) 的元素重复加入容器。
List接口常用的实现类有3个:ArrayList、LinkedList和Vector。
- ArrayList:基于单向链表,通过动态数组实现,支持随机访问,但是在List的中间插入和移除元素时较慢。
- Vector:和 ArrayList 类似,但它是线程安全的。
- LinkedList:基于双向链表实现,只能顺序访问,但是可以快速地在链表中间插入和删除元素。LinkedList在随机访问方面相对比较慢,但它的特性集较ArrayList更大。LinkedList 还可以用作栈、队列和双向队列。
实现类
ArrayList
ArrayList类扩展AbstractList并执行List接口。
ArrayList支持可随需要而增长的动态数组。
基于动态数组实现,支持随机访问,但是在List的中间插入和移除元素时较慢。
private static final int DEFAULT_CAPACITY = 10; // 默认初始大小
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size; 容器大小
ArrayList(); // 建立空的数组列表
ArrayList(Collection c); // 建立由c初始化的数组列表
ArrayList(int capacity); // 建立指定初始容量的数组列表
ArrayList 无参构造函数默认数组长度为10,添加时超过数组长度,会扩容到原来的1.5倍
底层原理
ArrayList底层是用数组实现的存储。 特点:查询效率高,增删效率低,线程不安全。我们一般使用它。
ArrayList底层使用Object数组来存储元素数据。所有的方法,都围绕这个核心的Object数组来开展。
ArrayList是可以存放任意数量的对象,长度不受限制,本质上就是通过定义新的更大的数组,将旧数组中的内容拷贝到新数组,来实现扩容。
LinkedList
LinkedList类扩展AbstractSeqentialList并执行List接口。
基于双向链表实现,只能顺序访问,但是可以快速地在链表中间插入和删除元素。LinkedList在随机访问方面相对比较慢,但它的特性集较ArrayList更大。LinkedList 还可以用作栈、队列和双向队列。
LinkedList(); // 建立空的链接列表
LinkedList(Collection c); // 建立由c初始化的链接列表
LinkedList本身定义了一些主要用于操作和访问列表的方法:
void addFirst(Object obj); // 在列头加元素
void addLast(Object obj); // 在列尾加元素
Object getFirst(); // 获得第一个元素
Object getLast(); // 获得最后一个元素
Object removeFirst(); // 获得第一个元素
Object removeLast(); // 获得最后一个元素
底层原理
LinkedList底层用双向链表实现的存储。特点:查询效率低,增删效率高,线程不安全。
双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向前一个节点和后一个节点。 所以,从双向链表中的任意一个节点开始,都可以很方便地找到所有节点。