Java 容器之 List
在 Java 的集合框架中,List 是 Collection 的重要子接口,以其有序、可重复的特点广泛应用于开发中。本文将详细探讨 List 的核心概念、主要实现类(如 ArrayList 和 LinkedList)的底层原理,以及使用中需要注意的常见问题。
List 简介
List 是一个接口,继承自 Collection,代表一个有序队列,允许元素重复。其核心特点是按照插入顺序存储元素,并支持通过索引快速访问。List 的抽象实现包括:
AbstractList:继承自AbstractCollection,实现了List接口的大部分方法(除size()和get(int)外),为具体实现类提供基础支持。AbstractSequentialList:继承自AbstractList,专注于链表操作,实现了基于索引的全部功能,适合顺序访问的场景。
常见的 List 实现类包括 ArrayList、LinkedList、Vector 和 Stack,其中 ArrayList 和 LinkedList 是日常开发中最常用的两种。
ArrayList 和 LinkedList
-
ArrayList:- 基于动态数组实现,容量有限,超出时自动扩容(默认初始容量为 10,扩容为原大小的 1.5 倍)。
- 随机访问快(时间复杂度 O(1)),但插入和删除较慢(受位置影响,可能需要移动大量元素)。
- 非线程安全。
-
LinkedList:- 基于双向链表实现,无容量限制。
- 插入和删除快(头尾操作 O(1),中间操作 O(n)),但随机访问慢(需遍历,O(n))。
- 非线程安全。
Vector 和 Stack
Vector:与ArrayList类似,但通过synchronized方法实现线程安全,适用于并发场景。Stack:继承自Vector,通过同步方法实现栈功能(LIFO,后进先出),也是线程安全的。
ArrayList 详解
基本特性
ArrayList 是基于动态数组的实现,其定义如下:
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- 实现
List接口,支持所有列表操作。 - 实现
RandomAccess接口,支持快速随机访问。 - 实现
Cloneable和Serializable,支持浅拷贝和序列化。 - 非线程安全。
数据结构
ArrayList 的核心字段包括:
private static final int DEFAULT_CAPACITY = 10; // 默认初始容量
transient Object[] elementData; // 存储元素的数组
private int size; // 当前元素个数
elementData:Object[]数组,实际存储元素,支持随机访问。size:记录当前元素数量,默认初始容量为 10,超出时扩容。
构造方法
ArrayList 提供三种构造方式:
public ArrayList() { // 默认构造,初始化空数组this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}public ArrayList(int initialCapacity) { // 指定初始容量if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);}
}
建议:初始化时指定容量,避免频繁扩容带来的性能开销。
扩容机制
添加元素时,若容量不足,ArrayList 会调用 grow() 方法扩容:
private void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容为 1.5 倍if (newCapacity - minCapacity < 0) newCapacity = minCapacity;elementData = Arrays.copyOf(elementData, newCapacity); // 数组复制
}
扩容涉及数组复制,性能开销较大,因此合理设置初始容量非常重要。
操作效率
- 访问:
get(int index)通过数组下标直接访问,时间复杂度 O(1)。 - 添加:
add(E e)(尾部添加):若无需扩容,O(1);若扩容,O(n)。add(int index, E element)(指定位置):需移动后续元素,O(n)。
- 删除:
remove(int index)需移动后续元素,O(n),位置越靠前开销越大。
Fail-Fast 机制
ArrayList 使用 modCount 记录结构变更次数(增删操作或扩容)。迭代或序列化时,若 modCount 变化,则抛出 ConcurrentModificationException,这就是 fail-fast 机制。
LinkedList 详解
基本特性
LinkedList 基于双向链表实现,其定义如下:
public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable
- 实现
List和Deque,可用作列表、队列或栈。 - 支持浅拷贝和序列化。
- 非线程安全。
数据结构
LinkedList 使用双向链表,核心字段包括:
transient int size = 0; // 节点数
transient Node<E> first; // 头节点
transient Node<E> last; // 尾节点private static class Node<E> { // 节点定义E item; // 数据Node<E> next; // 后继Node<E> prev; // 前驱...
}
操作效率
- 访问:
get(int index)需从头或尾遍历至目标位置,O(n)。建议使用迭代器遍历。 - 添加:
addFirst(E e)、addLast(E e):头尾操作,O(1)。add(int index, E element):需定位,O(n)。
- 删除:
remove(Object o)或remove(int index)需遍历定位,O(n),但调整指针开销为 O(1)。
序列化
与 ArrayList 类似,LinkedList 使用 transient 修饰字段,并重写 writeObject 和 readObject,仅序列化有效节点。
ArrayList vs. LinkedList
| 特性 | ArrayList | LinkedList |
|---|---|---|
| 线程安全 | 否 | 否 |
| 底层结构 | 动态数组 (Object[]) | 双向链表 |
| 随机访问 | O(1),支持 RandomAccess | O(n),不支持 |
| 插入/删除 | 尾部 O(1),其他 O(n) | 头尾 O(1),其他 O(n) |
| 内存占用 | 预留空间浪费 | 每个节点存储指针,占用更多 |
使用建议:ArrayList 适用于随机访问频繁的场景;LinkedList 适合频繁头尾操作的场景。但实际开发中,ArrayList 通常更常用,甚至 LinkedList 作者 Josh Bloch 也表示很少使用它。
List 使用中的常见问题
Arrays.asList 的陷阱
问题 1:基本类型数组转换异常
int[] arr = {1, 2, 3};
List list = Arrays.asList(arr);
// 输出: [[I@...], size=1
Arrays.asList 将 int[] 视为单一对象,而非元素集合。解决方法:
- 使用
Arrays.stream(Java 8+):List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList()); - 使用包装类型数组:
Integer[] arr = {1, 2, 3}; List<Integer> list = Arrays.asList(arr);
问题 2:不支持增删操作
Arrays.asList 返回的 List 是 Arrays 内部类 ArrayList,未实现 add 和 remove,调用时抛出 UnsupportedOperationException。
问题 3:原始数组修改影响 List
String[] arr = {"1", "2", "3"};
List<String> list = Arrays.asList(arr);
arr[1] = "4"; // list 同步变为 ["1", "4", "3"]
解决方法:新建 ArrayList 包装:
List<String> list = new ArrayList<>(Arrays.asList(arr));
List.subList 的陷阱
subList 返回的子列表与原列表共享存储,修改一方会影响另一方,且原列表结构变更可能导致 ConcurrentModificationException。
示例:内存泄漏
List<Integer> rawList = IntStream.rangeClosed(1, 100000).boxed().collect(Collectors.toList());
List<Integer> subList = rawList.subList(0, 1);
// rawList 无法被 GC 回收
解决方法:新建独立列表:
List<Integer> subList = new ArrayList<>(rawList.subList(0, 1));
示例:并发修改异常
List<Integer> list = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList());
List<Integer> subList = list.subList(1, 4);
list.add(0); // 修改原列表
subList.forEach(System.out::println); // 抛出 ConcurrentModificationException
解决方法:
- 使用
new ArrayList<>(subList)。 - 使用 Stream API:
List<Integer> subList = list.stream().skip(1).limit(3).collect(Collectors.toList());
总结
List 作为 Java 集合框架的重要组成部分,其实现类 ArrayList 和 LinkedList 各有优劣,开发者需根据场景选择合适的实现。同时,使用 Arrays.asList 和 subList 时需注意其潜在问题,避免踩坑。通过深入理解其底层原理和特性,我们可以更高效地编写健壮代码。
相关文章:
Java 容器之 List
在 Java 的集合框架中,List 是 Collection 的重要子接口,以其有序、可重复的特点广泛应用于开发中。本文将详细探讨 List 的核心概念、主要实现类(如 ArrayList 和 LinkedList)的底层原理,以及使用中需要注意的常见问题…...
ETL-kettle数据转换使用详解
一、excel转换成mysql 表格就按照我们刚才转换的表格来转换成MySQL数据 在MySQL数据库中创建数据库,这个根据自身情况。我就在现有test库中测试了。 根据以上步骤,新建转换。 构建流程图,选择excel输入和表输出 将两个组件连接起来 双击…...
【容器化】低版本docker拉取ubuntn 22.04镜像启动容器执行apt update提示 NO_PUBKEY 871920D1991BC93C
前置信息 宿主机信息 [root@localhost ~]# cat /etc/os-release NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR…...
Hive-04之存储格式、SerDe、企业级调优
一、主题 hive表的数据压缩和文件存储格式hive的自定义UDF函数hive的JDBC代码操作hive的SerDe介绍和使用hive的优化 二、要点 1. hive表的文件存储格式 Hive支持的存储数的格式主要有:TEXTFILE(行式存储) 、SEQUENCEFILE(行式存储)、ORC&…...
Makefile、Make和CMake:构建工具的三剑客
目录 1. Makefile 2. Make 3. CMake Makefile、Make、CMake的关系 在软件开发中,构建工具是必不可少的。它们帮助开发者自动化编译、链接和打包的过程,确保代码能够高效地转化为可执行文件。Makefile、Make和CMake是三个常见的构建工具,它…...
The “Rule-of-Zero“ should be followed (s4963)
Most classes should not directly handle resources, but instead, use members that perform resource handling for them: For memory, it can be std::unique_ptr, std::shared_ptr, std::vector…For files, it can be std::ofstream, std::ifstream…… Classes …...
Kotlin语言特性(二):泛型与注解
Kotlin语言特性(二):泛型与注解 一、引言 在上一篇文章中,我们介绍了Kotlin的三大核心特性。本文将深入探讨Kotlin的泛型和注解特性,并与Java进行对比,帮助你更好地理解和运用这些特性。 二、Kotlin泛型 2.1 泛型基础 2.1.1 声明泛型类 // Kotlin泛型类声明 class …...
FunPapers[3]:WWW‘25「快手」生成式回归预测观看时长
Sequence Generation Modeling for Continuous Value Prediction https://arxiv.org/pdf/2412.20211,www 2025. 文章目录 Sequence Generation Modeling for Continuous Value Prediction核心思想1. CVP常规方法是怎么做的?2. 观看时长预测和CVP是如何关…...
并发编程1
JAVA线程回顾 多线程 多个并行的线程来完成个自的任务,优点是程序响应速度更快,程序性能得到提升。 并行执行与并发执行 并发执行就是在单核CPU下,现成实际上是串行执行的,任务调度器将cpu的时间片分给不同的线程使用࿰…...
Hadoop之01:HDFS分布式文件系统
HDFS分布式文件系统 1.目标 理解分布式思想学会使用HDFS的常用命令掌握如何使用java api操作HDFS能独立描述HDFS三大组件namenode、secondarynamenode、datanode的作用理解并独立描述HDFS读写流程HDFS如何解决大量小文件存储问题 2. HDFS 2.1 HDFS是什么 HDFS是Hadoop中的一…...
从源到目标:深度学习中的迁移学习与领域自适应实践
云边有个稻草人-CSDN博客 目录 引言 一、迁移学习概述 1.1 迁移学习的类型 1.2 迁移学习的核心思想 1.3 迁移学习的应用场景 二、领域自适应(Domain Adaptation) 2.1 领域自适应的定义 2.2 领域自适应的挑战 2.3 领域自适应的核心方法 &#…...
WebRTC与PJSIP:呼叫中心系统技术选型指南
助力企业构建高效、灵活的通信解决方案 在数字化时代,呼叫中心系统的技术选型直接影响客户服务效率和业务扩展能力。WebRTC与PJSIP作为两大主流通信技术,各有其核心优势与适用场景。本文从功能、成本、开发门槛等维度为您深度解析,助您精准匹…...
使用IDEA如何隐藏文件或文件夹
选择file -> settings 选择Editor -> File Types ->Ignored Files and Folders (忽略文件和目录) 点击号就可以指定想要隐藏的文件或文件夹...
【人工智能】数据挖掘与应用题库(1-100)
1、涉及变化快慢的问题可以考虑使用导数来分析。 答案:对 2、导数的几何意义是曲线在某点处切线的斜率。 答案:对 3、函数在某点的左导数存在,则导数就存在。 答案:错 4、关于梯度下降算法,下列说法错误的是( ) 错误:梯度下降算法能找到函数精确的最小值。 5、正…...
腾讯云大模型知识引擎驱动的DeepSeek满血版医疗顾问大模型搭建实战
文章目录 1. 引言2. 什么是腾讯云大模型知识引擎(LKE)?核心优势功能特点应用场景 3. 模型搭建过程3.1 注册登录产品3.2 创建应用3.3 配置模型3.4 配置角色指令3.5 配置欢迎语3.6 配置知识库3.7 配置工作流3.8 启用联网搜索3.9 发布模型 4. 问…...
大白话页面加载速度优化的工具与实践案例
大白话页面加载速度优化的工具与实践案例 优化工具 Chrome开发者工具:这是个超好用的浏览器自带工具。就像你给车做检查的一套工具一样,能帮你查看页面加载的各种情况。比如说,你能在“Network”(网络)选项里看到每个…...
【JAVA面试题】什么是面向对象?谈谈你对面向对象的理解。
【JAVA面试题】什么是面向对象?谈谈你对面向对象的理解 在 Java 面试中,面向对象 是一个高频考点。它不仅是一种编程思想,更是现代软件开发的核心方法论。本文将从 面向对象的概念、与面向过程的对比、以及 面向对象的三大特性(封…...
解锁责任链模式:Java 实战与应用探秘
系列文章目录 后续补充~~~ 文章目录 一、责任链模式基础入门1.1 责任链模式的定义1.2 核心角色剖析1.2.1 抽象处理者(Handler)1.2.2 具体处理者(ConcreteHandler)1.2.3 客户端(Client) 1.3 类图结构展示 二…...
华为 Open Gauss 数据库在 Spring Boot 中使用 Flyway
db-migration:Flyway、Liquibase 扩展支持达梦(DM)、南大通用(GBase 8s)、OpenGauss 等国产数据库。部分数据库直接支持 Flowable 工作流。 开源代码仓库 Github:https://github.com/mengweijin/db-migrat…...
汽车电子电控软件开发中因复杂度提升导致的架构恶化问题
针对汽车电子电控软件开发中因复杂度提升导致的架构恶化问题,建议从以下方向进行架构优化和开发流程升级,以提升灵活性、可维护性和扩展性: 一、架构设计与模块化优化 分层架构与模块解耦 采用AUTOSAR标准的分层架构(应用层、运行…...
Agentic o3调度器与Gemma/Nemotron-H推理范式演进
1. 项目概述:一场悄然发生的模型推理范式迁移最近在几个核心AI工程团队的内部技术简报里,反复看到一个代号“TAI#149”的专项分析报告被高频引用——它不是某家公司的新品发布会通稿,而是一份由一线模型部署工程师自发整理、持续迭代的实战观…...
三年级下册语文第三单元作文:我做了一个小实验300字
三年级下册语文《我做了一个小实验》作文,重点要写清楚:做了什么实验实验前准备了什么实验过程看到了什么变化明白了什么道理我用夸克网盘分享了「三年级下册语文作文」,1-8单元。链接:https://pan.quark.cn/s/a80b7ca7f993这类作…...
DataStore vs SharedPreferences 迁移指南:告别 ANR,拥抱类型安全
DataStore vs SharedPreferences 迁移指南:告别 ANR,拥抱类型安全 一句话收益:掌握从 SharedPreferences 迁移到 Jetpack DataStore 的完整路径,彻底消除主线程 I/O 阻塞与类型安全隐患。 适用版本:Android API 21&…...
一文看懂 Hermes Agent 的 Prompt Builder:系统提示词到底拼进了什么?
一、先说结论:Prompt Builder 是 Hermes 的“提示词总装车间”普通 Chatbot 的系统提示词往往是一段固定文字,告诉模型“你是谁、怎么回答”。Hermes Agent 的 Prompt Builder 更像一条总装线:它会把身份、记忆、用户画像、项目规则、技能目录…...
【顶级EI复现】考虑用户行为基于扩散模型的电动汽车充电场景生成( Python + PyTorch代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 🎁…...
ISTA 7D-2007 全解析|运输包装温度循环测试标准(CSDN 完整版)
前言ISTA 7D-2007 是 ISTA 7 系列包装研发测试标准,专注于温控运输包装的温度环境模拟测试,用于评估保温箱、冷藏包、冷链包装在高低温循环环境下的隔热保温性能。该标准提供冬季 / 夏季、国内 / 国际、24h/48h/72h多套温度循环曲线,覆盖快递…...
三步解锁全网盘极速下载:免登录直链解析完整教程
三步解锁全网盘极速下载:免登录直链解析完整教程 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 …...
DS4Windows终极指南:如何让PlayStation手柄在Windows上完美运行
DS4Windows终极指南:如何让PlayStation手柄在Windows上完美运行 【免费下载链接】DS4Windows Like those other ds4tools, but sexier 项目地址: https://gitcode.com/gh_mirrors/ds/DS4Windows 想在Windows电脑上畅玩所有游戏,却只有PlayStation…...
【限时解密】:OpenAI DevDay未公布的Agent Runtime协议草案V2.1——它正悄然定义下一代智能体互操作标准
更多请点击: https://kaifayun.com 第一章:AI Agent智能体未来趋势 AI Agent正从单一任务执行者演变为具备自主目标分解、跨工具协同与持续环境反馈的类人智能体。其发展不再局限于模型规模扩张,而转向认知架构升级、可信机制构建与人机协作…...
ZStack控制台报错Failed to connect to console排查指南
1. 问题现场还原:不是连接失败,而是控制台页面直接报错弹窗Zstack 打开控制台报错——这六个字背后藏着一个在私有云运维一线高频出现、却常被误判为“网络不通”或“浏览器问题”的典型故障。我第一次遇到它是在给某制造企业做ZStack 4.5.2升级后的验收…...
