- ArrayList和LinkedList的差别主要来自于Array和LinkedList数据结构的不同。 ArrayList是基于数组实现的,LinkedList是基于双链表实现的。另外LinkedList类不
仅是List接口的实现类,可以根据索引来随机访问集合中的元素,除此之外,
LinkedList还实现了Deque接口,Deque接口是Queue接口的子接口,它代表一个双向
队列,因此LinkedList可以作为双向队列 ,栈(可以参见Deque提供的接口方法)和 List集合使用,功能强大。 - 因为Array是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快
的,可以直接返回数组中index位置的元素,因此在随机访问集合元素上有较好的性能。
Array获取数据的时间复杂度是O(1),但是要插入、删除数据却是开销很大的,因为这需
要移动数组中插入位置之后的的所有元素。 - 相对于ArrayList,LinkedList的随机访问集合元素时性能较差,因为需要在双向列表中
找到要index的位置,再返回;但在插入,删除操作是更快的。因为LinkedList不像
ArrayList一样,不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重
新装入一个新的数组,这是ArrayList最坏的一种情况,时间复杂度是O(n),而
LinkedList中插入或删除的时间复杂度仅为O(1)。ArrayList在插入数据时还需要更新索
引(除了插入数组的尾部)。 - LinkedList需要更多的内存,因为ArrayList的每个索引的位置是实际的数据,而
LinkedList中的每个节点中存储的是实际的数据和前后节点的位置。
ArrayList源码
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
transient Object[] elementData;
private int size;
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
}
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 boolean add(E e) {
linkLast(e);
return true;
}
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++;
}
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
}
if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}
}