【集合框架List接口】

👉 用 ArrayList 存数据,结果插入时卡住了?
👉 想删除某个元素,却发现索引错乱了?
👉 不知道该用 ArrayList 还是 LinkedList,选错了导致性能瓶颈?


一、List 是什么?—— 有序可重复的“列表”

🎯 核心特点

  • 有序(Ordered):元素按插入顺序排列
  • 允许重复:可以存储多个相同的值
  • 支持索引访问:可以通过 get(index) 快速定位元素

典型场景

  • 用户列表展示
  • 购物车商品管理
  • 日志记录

🖼️ 图示:List 的逻辑结构

+--------+    +--------+    +--------+
| index0 | -> | index1 | -> | index2 | -> ...
+--------+    +--------+    +--------+
| valueA |    | valueB |    | valueC |
+--------+    +--------+    +--------+

核心操作

  • 添加元素:add(E e)
  • 获取元素:get(int index)
  • 删除元素:remove(int index)

二、List 的核心实现类

1. ArrayList —— 基于“动态数组”的实现

🎯 核心特性
  • 底层是数组Object[] elementData
  • 支持快速随机访问:通过索引直接定位,时间复杂度 O(1)
  • 动态扩容:当容量不够时,自动扩展(默认扩容 1.5 倍)
  • 非线程安全
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
String first = list.get(0); // 快速获取第一个元素
🔍 动态扩容机制
private void grow(int minCapacity) {int oldCapacity = elementData.length;// 新容量 = 旧容量 + 旧容量/2 (即 1.5 倍)int newCapacity = oldCapacity + (oldCapacity >> 1);// 创建新数组,复制数据elementData = Arrays.copyOf(elementData, newCapacity);
}

内存变化

扩容前:[Apple][Banana]  (容量=2, size=2)
扩容后:[Apple][Banana][ ] (容量=3, size=2)

建议:初始化时指定合理容量,避免频繁扩容影响性能。

❌ 经典误区:中间插入/删除慢
// 错误:频繁在中间插入/删除,导致后面元素移动,性能 O(n)
list.add(1, "Orange"); // 插入到索引 1
list.remove(1);        // 删除索引 1

结论ArrayList 适合查询多、增删少的场景。


2. LinkedList —— 基于“双向链表”的实现

🎯 核心特性
  • 底层是双向链表:每个节点包含前后指针
  • 头尾增删快:时间复杂度 O(1)
  • 支持栈/队列操作:实现了 Deque 接口
  • 非线程安全
LinkedList<String> list = new LinkedList<>();
list.addFirst("Apple"); // 头插
list.addLast("Banana"); // 尾插
String first = list.getFirst(); // 快速获取第一个元素
🖼️ 图示:双向链表的内存布局
地址 2000: +--------+--------+--------+|prev=null| data=A |next=3000|+--------+--------+--------+地址 3000: +--------+--------+--------+|prev=2000| data=B |next=null|+--------+--------+--------+

逻辑结构

head                                   tail|                                      |v                                      v
+--------+    +--------+
|null|A|<--->|A|B|null|
+--------+    +--------+2000          3000

适用场景:频繁在头部或尾部增删元素,如消息队列、栈操作。

❌ 经典误区:随机访问慢
// 错误:频繁随机访问,导致遍历整个链表,性能 O(n)
String third = list.get(2); // 需要遍历两次才能找到第三个元素

结论LinkedList 适合头尾操作多、随机访问少的场景。


三、List 的常用方法详解

1. 添加元素

// 在末尾添加
list.add("Apple");// 在指定位置插入
list.add(1, "Banana"); // 插入到索引 1

2. 获取元素

// 通过索引获取
String first = list.get(0);// 获取第一个/最后一个元素
String first = list.get(0);
String last = list.get(list.size() - 1);

3. 删除元素

// 删除指定位置的元素
list.remove(1); // 删除索引 1 的元素// 删除指定对象(第一次出现)
list.remove("Apple");

4. 替换元素

// 替换指定位置的元素
list.set(1, "Grape"); // 将索引 1 的元素替换为 Grape

5. 查找元素

// 判断是否包含某个元素
boolean contains = list.contains("Apple");// 查找元素的位置
int index = list.indexOf("Apple"); // 返回第一个 Apple 的索引
int lastIndex = list.lastIndexOf("Apple"); // 返回最后一个 Apple 的索引

6. 子列表操作

// 获取子列表
List<String> subList = list.subList(1, 3); // 包含索引 1 和 2 的元素

四、List 的线程安全版本

1. Collections.synchronizedList() —— 简单粗暴的同步

List<String> syncList = Collections.synchronizedList(new ArrayList<>());synchronized (syncList) {syncList.add("Apple");
}

缺点

  • 整个 List 对象加锁,粒度过大,性能差。
  • 不支持并发读写,可能导致阻塞。

2. CopyOnWriteArrayList —— 写时复制的线程安全 List

🎯 核心特性
  • 写时复制:每次修改(addremove)都会创建一个新数组副本。
  • 适用于读多写少的场景:读操作无锁,写操作加锁但不影响读。
List<String> cowList = new CopyOnWriteArrayList<>();
cowList.add("Apple");
cowList.add("Banana");

适用场景

  • 并发读多、写少的场景,如日志记录、事件监听器等。

五、高频问题 & 高分回答

Q1: ArrayList 和 LinkedList 如何选择?

  • ArrayList:基于数组,查询快O(1)),增删慢O(n));
    适合随机访问多、增删少的场景。
  • LinkedList:基于链表,增删快O(1) 头尾),查询慢O(n));
    适合频繁头尾增删的场景,或实现栈/队列。
    我们项目中用户列表用 ArrayList,消息队列用 LinkedList

Q2: ArrayList 的扩容机制是怎样的?

  • 默认容量 10;
  • 扩容时,新容量 = 原容量 × 1.5;
  • 使用 Arrays.copyOf() 复制数据;
  • 扩容是耗时操作,建议初始化时指定合理容量

Q3: LinkedList 的优势和劣势是什么?

  • 优势:头尾增删快(O(1)),支持栈/队列操作;
  • 劣势:随机访问慢(O(n)),内存开销稍大(每个节点有前后指针)。
    适合频繁头尾操作的场景,如消息队列、栈操作。

Q4: CopyOnWriteArrayList 的工作原理?

  • 写时复制:每次修改(addremove)都会创建一个新数组副本;
  • 读操作无锁,写操作加锁但不影响读;
  • 适用于读多写少的场景,如日志记录、事件监听器等。

六、总结:一张表搞懂 List 的选型

场景推荐实现关键点
随机访问多、增删少ArrayList查询快,扩容注意
头尾增删多、随机访问少LinkedList头尾操作极快,随机访问慢
并发读多写少CopyOnWriteArrayList写时复制,读无锁

🔚 最后一句话

List 是 Java 集合框架中最基础、最常用的接口之一
它不仅仅是一个“容器”,更是我们日常开发中处理有序数据的核心工具。
只有当你真正理解了 ArrayList 的扩容机制、LinkedList 的双向链表结构,
以及 CopyOnWriteArrayList 的写时复制原理,
你才能写出高效、健壮、专业的 Java 代码!

希望这篇能帮你彻底搞懂 List 接口及其常见实现!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/93668.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/93668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《棒球百科》奥运会取消了棒球·野球1号位

⚾️ 奥运会棒球消失&复活之谜&#xff01;深度揭秘全球体育权力游戏 ⚾️❌ 2008年为何被踢出奥运&#xff1f;(Why Removed in 2008?)MLB的致命抵制➤ 奥运赛期撞车MLB常规赛白热化阶段&#xff01;➤ 球队老板拒放巨星&#xff1a;2000年悉尼奥运美国队仅剩"替补阵…

基于js和html的点名应用

分享一个在课堂或者是公司团建上需要点名的应用程序&#xff0c;开箱即用。1、双击打开后先选择人员名单&#xff08;可以随时更改的&#xff09;2、下面的滚动速度可以根据需求调整<!DOCTYPE html> <html lang"zh"> <head> <meta charset"…

【深度学习-基础知识】单机多卡和多机多卡训练

1. 单机多卡训练&#xff08;Single Machine, Multi-GPU&#xff09; 概念 在同一台服务器上&#xff0c;有多块 GPU。一个训练任务利用所有 GPU 并行加速训练。数据集存放在本地硬盘或共享存储上。 核心原理数据并行&#xff08;Data Parallelism&#xff09; 将一个 batch 划…

数据库原理及应用_数据库基础_第2章关系数据库标准语言SQL_SQL语言介绍数据库的定义和删除

前言 "<数据库原理及应用>(MySQL版)".以下称为"本书"中2.1节和2.2节第一部分内容 引入 本书P40:SQL(Structure Query Language结构化查询语言)是一种在关系数据库中定义和操纵数据的标准语言,是用户和数据库之间进行交流的接口. ---SQL是一种语言,是…

实变函数中集合E的边界与其补集的边界是否相等

在实变函数&#xff08;或一般拓扑学&#xff09;中&#xff0c;给定一个集合 E \subseteq \mathbb{R}^n &#xff08;或更一般的拓扑空间&#xff09;&#xff0c;集合 E 的边界&#xff08;boundary&#xff09;与 E 的补集 E^c 的边界是否相等&#xff1f; 即&#x…

# C++ 中的 `string_view` 和 `span`:现代安全视图指南

C 中的 string_view 和 span&#xff1a;现代安全视图指南 文章目录C 中的 string_view 和 span&#xff1a;现代安全视图指南目录1. 原始指针的痛点1.1 安全问题1.2 所有权不明确1.3 接口笨拙1.4 生命周期问题2. string_view 深入解析2.1 基本特性2.2 高效解析示例2.3 防止常见…

Linux学习-多任务(线程)

定义轻量级进程&#xff0c;实现多任务并发&#xff0c;是操作系统任务调度最小单位&#xff08;进程是资源分配最小单位 &#xff09;。创建由进程创建&#xff0c;属于进程内执行单元。- 独立&#xff1a;线程有8M 独立栈区 。 - 共享&#xff1a;与所属进程及进程内其他线程…

高级堆结构

一、二项堆&#xff08;Binomial Heap&#xff09;&#xff1a;理解「合并操作」的优化二项堆的核心优势是高效合并&#xff0c;类似 “二进制加法”。我们通过「合并两个二项堆」的伪代码和步骤来理解&#xff1a;核心结构伪代码&#xff1a;class BinomialTreeNode:def __ini…

系统学习算法 专题十七 栈

题目一&#xff1a;算法思路&#xff1a;一开始还是暴力解法&#xff0c;即遍历字符串&#xff0c;如果出现当前位置的字符等于后面的字符&#xff0c;则删除这两个字符&#xff0c;然后再从头遍历&#xff0c;如此循环即可但是这样时间复杂度很高&#xff0c;每删除一次就从头…

深入解析函数指针及其数组、typedef关键字应用技巧

目录 一、函数指针变量的创建 1、什么是函数指针变量&#xff1f; 2、函数是否有地址&#xff1f; 3、创建函数指针变量 4、函数指针类型解析 二、函数指针变量的使用 三、两段有趣的代码 1、解释 (*(void (*)())0)(); 2、解释 void (*signal(int, void(*)(int)))(int…

k8s集群搭建一主多从的jenkins集群

方案 --------------------- | Jenkins Master | | - 持久化配置 |<---(hostpath 存储) | - 自动容灾 | --------------------|| Jenkins JNLP 通信| ----------v---------- ------------------- | Jenkins Agent | | Kubernetes Pl…

重温k8s基础概念知识系列三(工作负载)

文章目录1、工作负载简述2、Deployment1.1、创建 Deployment1.2、检查 Deployment上线状态3、StatefulSet4、DaemonSet3.1、创建 DaemonSet3.2、运行DaemonSet5、Job5.1、运行示例 Job5.2、检查 Job 的状态6、CronJob上一节&#xff0c;我们复习了Pod相关知识&#xff0c;大多情…

开源 Arkts 鸿蒙应用 开发(十八)通讯--Ble低功耗蓝牙服务器

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发&#xff0c;公司安排开发app&#xff0c;临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 Arkts …

Go语言并发编程 ------ 锁机制详解

Go语言提供了丰富的同步原语来处理并发编程中的共享资源访问问题。其中最基础也最常用的就是互斥锁&#xff08;Mutex&#xff09;和读写锁&#xff08;RWMutex&#xff09;。1. sync.Mutex&#xff08;互斥锁&#xff09;Mutex核心特性互斥性/排他性&#xff1a;同一时刻只有一…

8月17日星期天今日早报简报微语报早读

8月17日星期天&#xff0c;农历闰六月廿四&#xff0c;早报#微语早读。1、《南京照相馆》领跑&#xff0c;2025年暑期档电影总票房破95亿&#xff1b;2、神舟二十号圆满完成第三次出舱任务&#xff1b;3、宇树G1人形机器人100米障碍赛再夺金牌&#xff1b;4、广东佛山新增报告基…

在QML中使用Chart组件

目录前言1. 如何安装 Chart 组件2. 创建 QML 工程时的常见问题3. 解决方案&#xff1a;改用 QApplication QQuickView修改主函数&#xff08;main.cpp&#xff09;4. QApplication 与 QGuiApplication 的差异为什么 Qt Charts 需要 QApplication&#xff1f;总结示例下载前言 …

【P40 6-3】OpenCV Python——图像融合(两张相同属性的图片按比例叠加),addWeighted()

P40 6-3 文章目录import cv2 import numpy as npback cv2.imread(./back.jpeg) smallcat cv2.imread(./smallcat1.jpeg)#只有两张图的属性是一样的才可以进行溶合 print(back.shape) print(smallcat.shape)result cv2.addWeighted(smallcat, 0.7, back, 0.3, 0) cv2.imshow(…

传输层协议 TCP(1)

传输层协议 TCP&#xff08;1&#xff09; TCP 协议 TCP 全称为 “传输控制协议(Transmission Control Protocol”). 人如其名, 要对数据的传输进行一个详细的控制; TCP 协议段格式 • 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去; • 32 位序号/32 位确认号: 后面详…

黎阳之光:以动态感知与 AI 深度赋能,引领电力智慧化转型新革命

当全球能源结构加速向清洁低碳转型&#xff0c;新型电力系统建设成为国家战略核心&#xff0c;电力行业正经历从传统运维向智慧化管理的深刻变革。2024 年《加快构建新型电力系统行动方案》明确提出&#xff0c;到 2027 年需建成全国智慧调度体系&#xff0c;实现新能源消纳率突…

自动驾驶中的传感器技术34——Lidar(9)

补盲lidar设计&#xff1a;机械式和半固态这里不再讨论&#xff0c;这里主要针对全固态补盲Lidar进行讨论1、系统架构设计采用Flash方案&#xff0c; 设计目标10m10%&#xff0c;实现30m距离的点云覆盖&#xff0c;同时可以验证不同FOV镜头的设计下&#xff0c;组合为多款产品。…