集合之List--ArrayList与LinkedList以及List与数组、Set的区别
在java中,List是最常用的集合类型之一,而ArrayList和LinkedList是List接口的两种主要实现。它们各有优缺点,适用于不同的场景。此外,List与数组、Set之间也有显著的区别。以下是对他们的详细对比和分析
一、ArrayList与LinkedList的区别
ArrayList
-
底层实现:基于动态数组
-
特点
-
随机访问速度快:通过索引访问元素的时间复杂度为O(1)。
-
插入和删除效率低:在中间插入或删除元素时,需要移动后续元素,时间复杂度为O(n)
-
内存占用少:只需要存储元素本身,不需要额外的指针
-
-
适用场景:
-
频繁读取数据(如遍历或随机访问)
-
数据量较大且插入/删除操作较少的场景
-
示例:
List<String> arrayList = new ArrayList<>(); arrayList.add("A"); arrayList.add("B"); arrayList.add("C"); System.out.println(arrayList.get(1)); // 输出:B
LinkedList
-
底层实现:基于双向链表
-
特点
-
插入和删除效率高:在链表中间插入或删除元素的时间复杂度为O(1).
-
随机访问速度慢:需要从头或尾遍历链表,时间复杂度为O(n)。
-
内存占用多:每个元素需要额外的指针(前驱和后继)
-
-
适用场景
-
频繁插入或删除数据的场景
-
需要实现栈、队列或双向队列的场景
-
示例:
List<String> linkedList = new LinkedList<>(); linkedList.add("A"); linkedList.add("B"); linkedList.add("C"); linkedList.add(1, "D"); // 在索引1处插入元素 System.out.println(linkedList); // 输出:[A, D, B, C]
ArrayList 与 LinkedList 对比
特性 | ArrayList | LinkedList |
---|---|---|
底层实现 | 动态数组 | 双向链表 |
随机访问速度 | O(1) | O(n) |
插入/删除速度 | O(n)(需要移动元素) | O(1)(只需修改指针) |
内存占用 | 较少(只存储元素) | 较多(需要存储指针) |
适用场景 | 频繁读取、数据量较大 | 频繁插入/删除、实现栈/队列 |
二、List与数组的区别
数组
-
固定长度:数组的长度在创建时确定,无法动态扩展。
-
类型固定:数组只能存储相同类型的元素。
-
性能高:数组的访问速度非常快,因为它是连续的内存块。
-
功能有限:数组没有提供丰富的方法(如添加、删除、查找等)。
示例:
String[] array = new String[3]; array[0] = "A"; array[1] = "B"; array[2] = "C"; System.out.println(array[1]); // 输出:B
List
-
动态长度:
List
的长度可以动态扩展。 -
类型灵活:
List
可以存储任意类型的对象(通过泛型指定)。 -
功能丰富:
List
提供了丰富的方法(如add
、remove
、contains
等)。 -
性能较低:相比数组,
List
的访问速度稍慢(尤其是LinkedList
)。
示例:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("C"); System.out.println(list.get(1)); // 输出:B
List 与数组对比
特性 | 数组 | List |
---|---|---|
长度 | 固定长度 | 动态长度 |
类型 | 只能存储相同类型 | 可以存储任意类型(泛型) |
性能 | 访问速度快 | 访问速度稍慢 |
功能 | 功能有限 | 功能丰富(添加、删除、查找等) |
适用场景 | 数据量固定、性能要求高 | 数据量动态变化、功能需求多 |
三、List与Set的区别
List
-
有序:元素按照插入顺序存储。
-
允许重复:可以存储相同的元素。
-
索引访问:可以通过索引访问元素。
-
实现类:
ArrayList
、LinkedList
、Vector
等。
示例:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("A"); // 允许重复 System.out.println(list); // 输出:[A, B, A]
Set
-
无序:元素不保证顺序(
LinkedHashSet
除外)。 -
不允许重复:相同的元素只能存储一次。
-
无索引访问:不能通过索引访问元素。
-
实现类:
HashSet
、LinkedHashSet
、TreeSet
等。
示例:
Set<String> set = new HashSet<>(); set.add("A"); set.add("B"); set.add("A"); // 不允许重复 System.out.println(set); // 输出:[A, B](顺序不确定)
List 与 Set 对比
特性 | List | Set |
---|---|---|
顺序 | 有序 | 无序(LinkedHashSet 除外) |
重复元素 | 允许重复 | 不允许重复 |
索引访问 | 支持 | 不支持 |
实现类 | ArrayList 、LinkedList 等 | HashSet 、TreeSet 等 |
适用场景 | 需要保留顺序和重复元素 | 需要去重、不关心顺序 |
四、 总结
-
ArrayList vs LinkedList:
-
ArrayList
适合频繁读取和随机访问的场景。 -
LinkedList
适合频繁插入和删除的场景。
-
-
List vs 数组:
-
数组适合数据量固定、性能要求高的场景。
-
List
适合数据量动态变化、功能需求多的场景。
-
-
List vs Set:
-
List
保留顺序和重复元素。 -
Set
去重且不保证顺序。
-
根据具体的业务需求,选择合适的数据结构可以显著提高程序的性能和可维护性