一、ArrayList集合
1-1、ArrayList的两种添加信息的方式
1-2、ArrayList集合底层逻辑
1、利用空参创建的集合,在底层创建一个默认长度为0的数组
2、添加第一个元素时,底层会创建一个新的长度为10的数组
3、存满时,会扩容1.5倍。
4、如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准。
二、LinkedList集合
2-1、LinkedList的特有API
LinkedList中的Node源码:
ListedList在任意位置插入元素:
import java.util.LinkedList;
public class LinkedListInsertExample {
public static void main(String[] args) {
// 创建LinkedList并添加初始元素
LinkedList<String> list = new LinkedList<>();
list.add("A");
list.add("B");
list.add("C");
// 打印插入前的链表:插入前的链表: [A, B, C]
System.out.println("插入前的链表: " + list);
// 在索引位置1插入元素"X"
list.add(1, "X");
// 打印插入后的链表:插入后链表: [A, X, B, C]
System.out.println("插入后链表: " + list);
}
}
2-2、ArrayList VS LinkedList
就整体使用频率而言,ArrayList通常比LinkedList更为常用。
1、ArrayList的常用性及其原因
-
随机访问性能优越:
- ArrayList基于数组实现,支持O(1)时间复杂度的随机访问。
- 在需要频繁访问列表中元素(如通过索引获取元素)的场景中,ArrayList具有显著优势。
-
动态扩容方便:
- ArrayList提供了动态扩容的功能,能够根据需要自动调整大小。(1.5倍)
- 这使得ArrayList在存储动态输入数据时更加灵活和方便。
进行排序和合并等操作时,ArrayList都是首选的数据结构。
2、LinkedList的适用场景及其局限性
-
插入和删除性能优越:
- LinkedList基于链表实现,支持O(1)时间复杂度的在任意位置插入和删除元素(前提是已知要插入或删除元素的位置)。
- 然而,在不知道位置的情况下,LinkedList的插入和删除操作需要遍历列表,时间复杂度为O(n)。
-
内存占用较大:
- 由于LinkedList中的每个元素都需要存储一个指向下一个元素的引用,因此其内存占用通常比ArrayList大。
LinkedList更适用于需要频繁在任意位置插入和删除元素的场景。
三、迭代器(Iterator)
3-1、迭代器(Iterator)源码
3-2、迭代器(Iterator)的ConcurrentModificationException
(并发修改异常)
Java集合框架中的大多数集合类(如ArrayList
、HashSet
等)都有一个内部计数器modCount
,用于记录集合被修改的次数。每当集合的结构发生变化(如添加、删除元素),modCount
就会增加。
迭代器在创建时,会保存一个创建时的expectedModCount
,这是迭代器期望的集合修改次数。在迭代过程中,每次调用next
方法时,迭代器都会检查当前集合的modCount
是否与expectedModCount
相等。如果不相等,说明集合在迭代过程中被修改了(不是通过迭代器自身的remove
方法),此时就会抛出ConcurrentModificationException
。
结论:在以后如何避免并发修改异常?
在使用迭代器或者是增强for遍历集合的过程中,不要使用集合的方法去添加或者删除元素即可。