都实现了List接口。都是线程不安全的。(区别:简单来说 ArrayList 只有查询快,其余都是LinkedList快,LinkedList更占内存)
-
ArrayList是基于索引的数据接口,底层是动态数组。它可以以O(1)时间复杂度对元素进行随机访问。
-
LinkedList使用双向链表实现存储,每一个元素都和它的前一个和后一个元素链接在一起,这种情况下,查找某个元素的时间复杂度是O(n).但是相对于ArrayList,它的插入、添加、删除操作速度更快。因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。
-
LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。
-
如果遇到多个线程操作同一个容器的场景,可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后使用。(这是对装潢模式的应用,将已有对象传入到另一个类的构造器中创建新的对象来增强实现).
-
对于随机访问set()和get(),ArrayList要优于LinkedList,因为LinkedList要移动指针,ArrayList并发add()可能出现数组下标越界异常。
对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。
ArrayList部分源码
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;
//默认初始容量为10
private static final int DEFAULT_CAPACITY = 10;
//用于空实例的共享空数组实例
private static final Object[] EMPTY_ELEMENTDATA = {};
//用于默认大小的空实例的共享空数组实例。
//将其与EMPTY_ELEMENTDATA区分开来,以了解添加第一个元素时需要膨胀多少。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//存储ArrayList元素的数组缓冲区。
//ArrayList的容量是这个数组缓冲区的长度。
//任何带有elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA的空ArrayList将在添加第一个元素时扩展为DEFAULT_CAPACITY
transient Object[] elementData; // 非私有简化嵌套类访问
//ArrayList的大小(包含的元素数量)。
private int size;
/**
* 构造一个具有指定初始容量的空列表。
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//构造一个初始容量为10的空列表。
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
}
LinkedList部分源码
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
transient int size = 0;
//指向第一个节点的指针
transient Node<E> first;
//指向最后一个节点的指针。
transient Node<E> last;
//构造一个空列表。
public LinkedList() {
}
/**
构造一个包含指定集合元素的列表,按照集合的迭代器返回元素的顺序。
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException 如果指定的集合为空
*/
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
//链接e作为第一个元素。
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
//链接e作为最后一个元素。
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
//将元素e插入到非空节点succ之前。
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
//解除非空第一个节点f的链接。
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
//解除最后一个非空节点l的链接。
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}
}
结