当前位置: 首页 > news >正文

【数据结构】List 详解

目录

1. List 的核心概念

核心特性:

2. List 的抽象数据类型(ADT)

基本操作

3. List 的主要实现方式

3.1 顺序表(基于数组)

3.2 链表(基于节点)

4. Java 中的 List 接口及实现类

4.1 List 接口的继承关系

4.2 主要实现类对比

5. 具体实现详解

5.1 ArrayList - 基于动态数组的实现

5.2 LinkedList - 基于链表的实现

6. 时间复杂度分析

7. 使用场景和选择建议

选择 ArrayList 当:

选择 LinkedList 当:

示例:性能对比场景

8. 常见算法和应用

8.1 列表反转

8.2 列表排序


1. List 的核心概念

​List(列表/线性表)​​ 是一种线性数据结构,它表示一个​​有序的、可重复的​​元素序列。

核心特性:

  1. ​有序性​​:元素按照插入的顺序存储,每个元素都有确定的位置(索引)

  2. ​可重复性​​:允许包含重复的元素

  3. ​动态大小​​:大多数实现支持动态扩容

  4. ​随机访问​​:可以通过整数索引直接访问任何位置的元素


2. List 的抽象数据类型(ADT)

在讨论具体实现之前,先了解 List 应该支持哪些基本操作:

基本操作

操作

方法签名

描述

​添加​

add(E element)

在末尾添加元素

​插入​

add(int index, E element)

在指定位置插入元素

​获取​

get(int index)

获取指定位置的元素

​设置​

set(int index, E element)

修改指定位置的元素

​删除​

remove(int index)

删除指定位置的元素

​删除元素​

remove(Object o)

删除第一次出现的指定元素

​大小​

size()

返回元素个数

​判空​

isEmpty()

判断是否为空

​包含​

contains(Object o)

判断是否包含某元素

​查找​

indexOf(Object o)

返回元素第一次出现的索引

​清空​

clear()

清空所有元素


3. List 的主要实现方式

List 有两种经典的实现方式,对应不同的底层数据结构:

3.1 顺序表(基于数组)

  • ​底层结构​​:动态数组

  • ​代表实现​​:ArrayListVector

  • ​特点​​:

    • 内存连续分配

    • 支持快速随机访问(O(1))

    • 尾部操作高效,中间插入/删除需要移动元素

3.2 链表(基于节点)

  • ​底层结构​​:节点通过指针连接

  • ​代表实现​​:LinkedList

  • ​特点​​:

    • 内存非连续分配

    • 插入删除高效(O(1),已知位置时)

    • 随机访问需要遍历(O(n))


4. Java 中的 List 接口及实现类

4.1 List 接口的继承关系

// List 是一个泛型接口
public interface List<E> extends Collection<E> {// 定义了一系列列表操作的方法
}

4.2 主要实现类对比

特性

ArrayList

LinkedList

Vector

​底层结构​

动态数组

双向链表

动态数组

​线程安全​

是(同步)

​随机访问​

​O(1)​​ - 很快

O(n) - 慢

​O(1)​​ - 很快

​头部插入​

O(n) - 需要移动元素

​O(1)​​ - 很快

O(n) - 需要移动元素

​尾部插入​

​O(1)​​ 平均 - 快

​O(1)​​ - 很快

​O(1)​​ 平均 - 快

​中间插入​

O(n) - 需要移动元素

​O(1)​​(已知位置时)

O(n) - 需要移动元素

​内存开销​

较小(只存数据)

较大(需要存储指针)

较小(只存数据)


5. 具体实现详解

5.1 ArrayList - 基于动态数组的实现

// ArrayList 的基本使用
List<String> arrayList = new ArrayList<>();// 添加元素
arrayList.add("Apple");
arrayList.add("Banana");
arrayList.add(1, "Orange"); // 在索引1处插入// 访问元素
String fruit = arrayList.get(0); // "Apple"// 遍历方式1:for循环(随机访问特性体现)
for (int i = 0; i < arrayList.size(); i++) {System.out.println(arrayList.get(i));
}// 遍历方式2:增强for循环
for (String item : arrayList) {System.out.println(item);
}// 遍历方式3:迭代器
Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()) {System.out.println(iterator.next());
}

​ArrayList 的扩容机制​​:

// 当容量不足时,ArrayList会自动扩容
List<Integer> list = new ArrayList<>(5); // 初始容量5
for (int i = 0; i < 10; i++) {list.add(i); // 当添加第6个元素时,会触发扩容
}// 扩容过程(简化):
// 1. 创建新数组(通常是原容量的1.5倍)
// 2. 将旧数组元素拷贝到新数组
// 3. 更新内部数组引用

5.2 LinkedList - 基于链表的实现

// LinkedList 的基本使用
List<String> linkedList = new LinkedList<>();// 添加元素
linkedList.add("First");
linkedList.add("Second");
linkedList.addFirst("Head"); // 链表特有的方法
linkedList.addLast("Tail");  // 链表特有的方法// LinkedList 还实现了 Deque 接口,可以用作栈或队列
Deque<String> deque = (Deque<String>) linkedList;
deque.offerFirst("New Head");
deque.offerLast("New Tail");

​链表节点结构​​:

// 双向链表节点的简化表示
class Node<E> {E item;         // 存储的数据Node<E> next;   // 指向下一个节点Node<E> prev;   // 指向上一个节点
}

6. 时间复杂度分析

操作

ArrayList

LinkedList

说明

​get(int index)​

O(1)

O(n)

ArrayList通过索引直接计算地址

​add(E element)​

O(1) 平均

O(1)

尾部添加

​add(int index, E element)​

O(n)

O(1)(已知位置)

中间插入

​remove(int index)​

O(n)

O(1)(已知位置)

中间删除

​set(int index, E element)​

O(1)

O(n)

修改指定位置

​contains(Object o)​

O(n)

O(n)

需要遍历查找

​indexOf(Object o)​

O(n)

O(n)

需要遍历查找


7. 使用场景和选择建议

选择 ArrayList 当:

  • ​频繁随机访问​​元素(按索引读取)

  • ​主要在尾部进行添加/删除​​操作

  • 内存相对紧张,希望减少开销

  • 不需要线程安全(或可以自行处理同步)

选择 LinkedList 当:

  • ​频繁在任意位置插入/删除​​元素

  • 需要实现​​栈、队列、双端队列​

  • 内存充足,可以接受额外指针开销

  • 列表规模很大,中间操作频繁

示例:性能对比场景

// 场景1:频繁随机访问 - 适合ArrayList
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100000; i++) {int value = list.get(i); // ArrayList: O(1), LinkedList: O(n)
}// 场景2:频繁在头部插入 - 适合LinkedList  
List<Integer> list = new LinkedList<>();
for (int i = 0; i < 100000; i++) {list.add(0, i); // ArrayList: O(n), LinkedList: O(1)
}

8. 常见算法和应用

8.1 列表反转

// 方法1:使用Collections工具类
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Collections.reverse(list);// 方法2:手动实现
public static <T> void reverseList(List<T> list) {int left = 0, right = list.size() - 1;while (left < right) {T temp = list.get(left);list.set(left, list.get(right));list.set(right, temp);left++;right--;}
}

8.2 列表排序

List<Integer> numbers = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5, 9));// 自然排序
Collections.sort(numbers);// 自定义排序
Collections.sort(numbers, (a, b) -> b - a); // 降序// 使用Stream API排序
List<Integer> sorted = numbers.stream().sorted().collect(Collectors.toList());

​List 是最基础、最常用的数据结构之一​​,理解其特性和实现方式对于编程至关重要:

  1. ​ArrayList​​:基于动态数组,​​查询快,增删慢​​,适合查询多的场景

  2. ​LinkedList​​:基于双向链表,​​增删快,查询慢​​,适合频繁插入删除的场景

  3. ​Vector​​:线程安全的ArrayList,但性能较差,一般不推荐使用

​选择原则​​:

  • 80%的情况下,​​ArrayList 是默认选择​

  • 只有在需要频繁在列表中间操作时,才考虑 LinkedList

  • 在多线程环境下,考虑使用 Collections.synchronizedList()CopyOnWriteArrayList

http://www.dtcms.com/a/406241.html

相关文章:

  • 网站哪个做的好织梦cms手机网站
  • Golang面试-Channel
  • Go channel 的底层实现
  • uniapp USB UVC 摄像头调用的最佳实现 支持Android5到Android16 v2
  • 【uni-app】树形结构数据选择框
  • 视频解析网站甜品蛋糕网站建设策划书
  • PostgreSQL 中序列(Sequence)的详细用法
  • 超低延迟与高并发保障:互联网直播点播平台EasyDSS如何成为企业级现场直播的“技术底座”?
  • 一种个性化认知型人形机器人端到端的架构设计
  • Frp内网穿透v0.64.0
  • 9.25交作业
  • 【原理与应用】3-flink安装与部署
  • 网站经营性备案难不难良品铺子网络营销策划书
  • 永磁同步电机驱动控制系统设计(论文+仿真)
  • Cherry Studio+Ollama+大模型+向量模型,实现RAG私有知识库。智能体实现EXCEL转化为一个报表图表
  • Ansible Playbook 入门指南:从基础到实战
  • 什么是提示词追问?
  • 【MD编辑器Typora】Typora最新 V1.12.1版:轻量级 Markdown 编辑器详细图文下载安装使用指南 【办公学习神器之MD文本编辑器】
  • 内外外贸购物网站建设seo基础优化包括哪些内容
  • 冰雪守护者:输电线路图像识别覆冰监测系统为电网保驾护航
  • MCU的闪存(FLASH)存储器的接口寄存器
  • 软件毕设代做网站阿里云建设网站的流程
  • 第12篇|[特殊字符] Freqtrade 交易所接入全解:API、WebSocket、限频配置详解
  • k8s etcd 运行错误 failed to find plugin “flannel“ in path [/usr/lib/cni]
  • 【LeetCode - 每日1题】计算三角形最小路径和
  • 信息安全工程师考点-安全体系结构
  • 小说网站制作开源山东网站开发
  • 医院网站建设的目的大学跳蚤市场网站建设
  • Python SQLite模块:轻量级数据库的实战指南
  • 学习HAL库STM32F103C8T6(SPI、门禁密码实验)