您好,登录后才能下订单哦!
在Java集合框架中,ArrayList
和LinkedList
是两种常用的列表实现类。它们都实现了List
接口,但在底层实现、性能特点和使用场景上有显著的区别。本文将详细探讨ArrayList
和LinkedList
的区别、扩容机制以及底层的实现方式。
ArrayList:ArrayList
的底层是基于动态数组实现的。它使用一个数组来存储元素,并且可以根据需要自动扩容。
LinkedList:LinkedList
的底层是基于双向链表实现的。它通过节点(Node)来存储元素,每个节点包含对前一个节点和后一个节点的引用。
ArrayList:
ArrayList
支持通过索引快速访问元素,时间复杂度为O(1)。ArrayList
的内存占用相对较小,因为它只需要存储元素和数组的容量。LinkedList:
LinkedList
不支持通过索引快速访问元素,访问某个元素需要从头或尾开始遍历,时间复杂度为O(n)。LinkedList
的内存占用相对较大,因为每个节点除了存储元素外,还需要存储对前一个节点和后一个节点的引用。ArrayList:适用于需要频繁随机访问元素的场景,例如读取操作远多于插入和删除操作的场景。
LinkedList:适用于需要频繁插入和删除元素的场景,例如实现队列或栈等数据结构。
ArrayList
在创建时,可以指定初始容量。如果不指定初始容量,默认的初始容量为10。
List<Integer> list = new ArrayList<>(); // 默认初始容量为10
List<Integer> listWithCapacity = new ArrayList<>(20); // 指定初始容量为20
当ArrayList
中的元素数量超过当前数组的容量时,ArrayList
会自动进行扩容。扩容的过程如下:
oldCapacity + (oldCapacity >> 1)
)。ArrayList
的内部数组引用指向新数组。private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量为旧容量的1.5倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
扩容操作涉及到数组的复制,因此会带来一定的性能开销。为了避免频繁扩容,可以在创建ArrayList
时指定一个较大的初始容量,或者在添加大量元素之前调用ensureCapacity(int minCapacity)
方法来确保容量足够。
list.ensureCapacity(1000); // 确保容量至少为1000
LinkedList
的底层是基于双向链表实现的。每个节点(Node)包含三个部分:
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
是基于链表实现的,插入和删除操作只需要调整节点的引用,而不需要移动元素。
插入操作:
删除操作:
// 插入操作
void linkBefore(E e, Node<E> succ) {
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++;
}
// 删除操作
E unlink(Node<E> x) {
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;
}
由于LinkedList
的每个节点都需要存储前驱和后继节点的引用,因此它的内存占用比ArrayList
要大。每个节点除了存储元素外,还需要额外的内存来存储引用。
ArrayList
和LinkedList
是Java集合框架中两种常用的列表实现类,它们在底层实现、性能特点和使用场景上有显著的区别。
ArrayList:基于动态数组实现,支持快速随机访问,但在中间插入和删除元素时性能较差。适用于需要频繁读取操作的场景。
LinkedList:基于双向链表实现,支持快速插入和删除操作,但在随机访问时性能较差。适用于需要频繁插入和删除操作的场景。
在实际开发中,应根据具体需求选择合适的列表实现类。如果需要频繁读取元素,ArrayList
是更好的选择;如果需要频繁插入和删除元素,LinkedList
则更为合适。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。