List源码分析

 

java.util

 

接口 List<E>

 

所有超级接口:

 

Collection<E>, Iterable<E>

 

所有已知实现类:

 

AbstractList, AbstractSequentialList, ArrayList, AttributeList, CopyOnWriteArrayList, LinkedList, RoleList, RoleUnresolvedList, Stack, Vector

 

List接口在java.util包里,继承Collection<E>超级接口

 

主要分析一下:ArrayListLinkedListVector

 

 

ArrayList

LinkedList

Vector

数据结构

Object[]

size

Node<E> first

Node<E> last

size

Object[]

size

初始值

10

0

10

是否有序

有序可重复

有序可重复

有序可重复

安全性

不安全

不安全

线程安全

扩容方案

每次ADD扩容0.5

可指定长度

自增长

容量不够时2倍扩容

可指定长度

性能分析

查找快,增删慢

查找慢,增删快

查找快,增删慢

是否可变

不可变

不可变

可变

 

1,ArrayList

 

Add():添加方法

 

对于每次ADD都扩容,官方文档解释如下:

 

The add operation runs in amortized constant time, that is, adding n elements requires O(n) time. All of the other operations run in linear time (roughly speaking). The constant factor is low compared to that for the LinkedList implementation.

 

意为:分担时间开销

 

Remove():删除方法


 

Get():查找方法

 

 

直接通过数组下标读取。

 

由上述代码分析可见:

 

ArrayList频繁的数组拷贝操作性能低下。add/remove慢,查找快。

 

使用建议:

 

  • 创建线程安全的List方式如下:

 

 List list = Collections.synchronizedList(new ArrayList(...));

 

  • 指定list大小

 

在知道List大小情况下,建议在创建时指定list大小,方法为ensureCapacity(int minCapacity)         

 

  • 遍历方式

 

ArrayList继承AbstractList接口,实现RandomAccess接口,使用for循环遍历,效率高于Iterator

 

AbstractList接口是对“随机访问”数据存储(如数组)支持

 

RandomAccess接口是List 实现所使用的标记接口,用来表明其支持快速(通常是固定时间)随机访问。

 

2LinkedList

 

链表的数据结构:

 

Node(prev)

item

Node(next)

Add():添加方法


 

Remove():删除方法

Get():查找方法

 

使用二分法遍历查找。

 

由上述代码分析可见:

 

LinkedList使用链表数据结构。add/remove较快,查找慢。

 

  • 创建线程安全的List方式如下:

 

 List list = Collections.synchronizedList(new LinkedList(...));

 

  • 遍历方式

 

LinkedList继承AbstractSequentialList接口,实现Deque接口,使用Iterator循环遍历,效率高于for

 

AbstractSequentialList接口是对“连续访问”数据存储(如链接列表)支持的

 

Deque接口是双端队列一个线性 collection,支持在队列两端插入和移除元素。

 

3Vector

 

Add():添加方法

 

 

 

容量不够时按照当前数组长度的2倍进行扩容。

 

Remove():删除方法

 

ArrayList

 

Get():查询方法

 

ArrayList

 

使用建议:

 

  • 线程安全,方法均加了synchronized关键字

 

注意,因为vector提供set方法修改值,导致在iterator时会造成不安全。

 

  • 指定向量大小

 

在知道向量大小情况下,建议在创建时指定向量大小,方法为ensureCapacity(int minCapacity)         

 

  • 遍历方式

 

vector继承AbstractList接口,实现RandomAccess接口,使用for循环遍历,效率高于Iterator

 

 

 

 

 

 

 

(请详细解析相关概念和描述,联网解析,中文解析)看看关于LinkedList源码开头的注释 • Doubly-linked list implementation of the {@code List} and {@code Deque} • interfaces. Implements all optional list operations, and permits all • elements (including {@code null}). * • <p>All of the operations perform as could be expected for a doubly-linked • list. Operations that index into the list will traverse the list from • the beginning or the end, whichever is closer to the specified index. * • <p><strong>Note that this implementation is not synchronized.</strong> • If multiple threads access a linked list concurrently, and at least • one of the threads modifies the list structurally, it <i>must</i> be • synchronized externally. (A structural modification is any operation • that adds or deletes one or more elements; merely setting the value of • an element is not a structural modification.) This is typically • accomplished by synchronizing on some object that naturally • encapsulates the list. 从这段注释中,我们可以得知 LinkedList 是通过一个双向链表来实现的,它允许插入所有元素,包括 null,同时,它是线程不同步的。 LinkedList集合底层结构是带头尾指针的双向链表。 LinkedList是非线程安全的。 LinkedList集合中存储元素的特点:有序可重复,元素带有下标,从0开始,以1递增。 LinkedList集合的优点:在指定位置插入/删除元素的效率较高;缺点:查找元素的效率不如ArrayList
最新发布
04-04
<think>好的,我现在需要帮助用户解析Java LinkedList的源码注释,特别是关于双向链表、线程安全性和插入删除效率的部分。用户提到了几个引用,我需要结合这些引用来组织回答。 首先,用户提供的引用中有关于LinkedList的基本结构,比如双向链表,继承自AbstractSequentialList,以及线程不安全的问题。引用[3]提到LinkedList是双向链表,可以作为堆栈、队列等使用,这应该作为开头部分的结构描述。 接下来是线程安全性。引用[2]和[4]都说明了LinkedList是线程不安全的,需要外部同步,或者使用Collections.synchronizedList。引用[4]还详细解释了modCount和ConcurrentModificationException的产生机制,这部分需要详细说明,尤其是迭代器遍历时多线程修改的问题。 然后是插入和删除效率。引用[1]指出在指定位置插入时LinkedList比ArrayList高效,因为不需要数组复制。但可能用户需要更详细的解释,比如节点操作的时间复杂度和具体方法,比如add和remove。引用[5]中的remove方法解析,通过遍历找到元素后调用unlink,说明删除操作的时间复杂度是O(n),但unlink本身是O(1)。需要区分按索引和按元素删除的不同情况。 源码注释中的关键点可能需要提取,比如线程不安全、双向链表结构、允许null值等。用户还希望中文解析,所以需要用简洁的中文解释这些概念。 此外,用户的问题还包括生成相关问题,需要根据内容提出相关问题,比如结构特点、线程安全保证、ArrayList的比较、应用场景等。 需要确保回答结构清晰,分点说明,引用正确的来源,并在末尾添加相关问题。同时注意使用中文,避免使用Markdown格式,但根据用户系统指令,可能允许适当的分段和代码块。 最后检查是否覆盖了用户的所有需求:源码注释中的概念、双向链表、线程安全、插入删除效率,以及引用相关的内容。确保每个部分都有对应的引用支持,例如线程安全部分引用[2][4],插入删除效率引用[1][5],结构部分引用[3]。</think>### Java LinkedList 源码注释解析 #### 1. **双向链表结构** LinkedList 是基于双向链表实现的集合类,每个节点(`Node`)包含前驱指针(`prev`)、后继指针(`next`)和存储的数据(`item`)。这种结构使得插入和删除操作的时间复杂度为 $O(1)$(仅操作指针),但查找元素需要 $O(n)$ 时间(需遍历链表)[^3]。 源码注释中明确说明: > `LinkedList` 实现了 `List` 和 `Deque` 接口,可作为队列、堆栈或双端队列使用。 #### 2. **线程安全性** LinkedList **非线程安全**,多线程环境下需通过外部同步控制(如 `Collections.synchronizedList`)保证安全[^2][^4]。源码注释指出: > 若多个线程并发修改链表,需通过外部同步机制保证一致性。迭代器遍历时若其他线程修改链表结构,会触发 `ConcurrentModificationException`。 具体机制: - **`modCount` `expectedModCount`**: 迭代器初始化时会记录 `modCount`(链表结构修改计数器)。遍历过程中若发现 `modCount != expectedModCount`,说明链表被外部修改,立即抛出异常。 #### 3. **插入删除效率** - **插入效率**: 在指定索引位置插入元素时,LinkedList 只需调整相邻节点的指针($O(1)$),而 ArrayList 需要复制数组($O(n)$)。因此,频繁插入场景下 LinkedList 更高效[^1]。 源码中 `add(int index, E element)` 方法通过 `node(index)` 找到目标位置节点后直接插入新节点。 - **删除效率**: `remove(Object o)` 方法需遍历链表找到目标元素($O(n)$),但实际删除操作(`unlink(Node<E> x)`)仅需修改指针($O(1)$)[^5]。例如删除首个匹配的 `null` 值: ```java for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); // 断开前后指针,更新链表头尾 return true; } } ``` #### 4. **其他关键注释说明** - **允许 `null` 值**:LinkedList 允许存储 `null`,在 `remove` 和 `contains` 方法中需特殊处理。 - **继承关系**:继承自 `AbstractSequentialList`,实现了链式存储的抽象逻辑[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值