我对为什么arraylist 比linkedlist 更快的理解是,使用arraylist 你基本上只需要一个操作——更新数组末尾元素的引用,而使用链表你必须做更多的事情,例如创建一个新节点,更新2引用,遍历链表并更新最后一个节点以指向新节点等。
但是我不确定java如何实现这些。arraylist 如何知道“最后一个”元素在哪里,它是存储最后一个元素的值还是遍历数组并在最后一个元素之后添加一个新元素?
而链表,它们是存储对列表中最后一个节点的引用,还是遍历整个列表到达末尾?
我对为什么arraylist 比linkedlist 更快的理解是,使用arraylist 你基本上只需要一个操作——更新数组末尾元素的引用,而使用链表你必须做更多的事情,例如创建一个新节点,更新2引用,遍历链表并更新最后一个节点以指向新节点等。
但是我不确定java如何实现这些。arraylist 如何知道“最后一个”元素在哪里,它是存储最后一个元素的值还是遍历数组并在最后一个元素之后添加一个新元素?
而链表,它们是存储对列表中最后一个节点的引用,还是遍历整个列表到达末尾?
看源码:
数组列表:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
链表:
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++;
}
数组列表仅在某些操作中更快。如果在数组中间添加一个元素,则 arraylist 基本上需要将所有数据复制到一个新数组中。只有当数组列表已经为新数据分配了空间时,它才会在插入空的数据时快速(通常在最后)。按索引读取/更新非常快。
LinkedList 在插入时速度很快,因为它从不需要复制整个数组。但是访问链表中的数据很慢,因为您需要“遍历”所有元素,直到找到要查找的元素。
您可以随时查看java.*
类的来源。
但是,特别回答您的问题:类中有一个int
字段ArrayList
,其中包含填充的内部数组区域的当前大小。当您在ArrayList
对象中添加新值时,此字段会递增,然后直接寻址到内部数组中的该元素。