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标准的分层架构(应用层、运行…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...