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

Java 容器之 List

在 Java 的集合框架中,ListCollection 的重要子接口,以其有序、可重复的特点广泛应用于开发中。本文将详细探讨 List 的核心概念、主要实现类(如 ArrayListLinkedList)的底层原理,以及使用中需要注意的常见问题。


List 简介

List 是一个接口,继承自 Collection,代表一个有序队列,允许元素重复。其核心特点是按照插入顺序存储元素,并支持通过索引快速访问。List 的抽象实现包括:

  • AbstractList:继承自 AbstractCollection,实现了 List 接口的大部分方法(除 size()get(int) 外),为具体实现类提供基础支持。
  • AbstractSequentialList:继承自 AbstractList,专注于链表操作,实现了基于索引的全部功能,适合顺序访问的场景。

常见的 List 实现类包括 ArrayListLinkedListVectorStack,其中 ArrayListLinkedList 是日常开发中最常用的两种。

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 接口,支持快速随机访问。
  • 实现 CloneableSerializable,支持浅拷贝和序列化。
  • 非线程安全。

数据结构

ArrayList 的核心字段包括:

private static final int DEFAULT_CAPACITY = 10; // 默认初始容量
transient Object[] elementData; // 存储元素的数组
private int size; // 当前元素个数
  • elementDataObject[] 数组,实际存储元素,支持随机访问。
  • 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
  • 实现 ListDeque,可用作列表、队列或栈。
  • 支持浅拷贝和序列化。
  • 非线程安全。

数据结构

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 修饰字段,并重写 writeObjectreadObject,仅序列化有效节点。


ArrayList vs. LinkedList

特性ArrayListLinkedList
线程安全
底层结构动态数组 (Object[])双向链表
随机访问O(1),支持 RandomAccessO(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.asListint[] 视为单一对象,而非元素集合。解决方法

  • 使用 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 返回的 ListArrays 内部类 ArrayList,未实现 addremove,调用时抛出 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 集合框架的重要组成部分,其实现类 ArrayListLinkedList 各有优劣,开发者需根据场景选择合适的实现。同时,使用 Arrays.asListsubList 时需注意其潜在问题,避免踩坑。通过深入理解其底层原理和特性,我们可以更高效地编写健壮代码。

相关文章:

Java 容器之 List

在 Java 的集合框架中&#xff0c;List 是 Collection 的重要子接口&#xff0c;以其有序、可重复的特点广泛应用于开发中。本文将详细探讨 List 的核心概念、主要实现类&#xff08;如 ArrayList 和 LinkedList&#xff09;的底层原理&#xff0c;以及使用中需要注意的常见问题…...

ETL-kettle数据转换使用详解

一、excel转换成mysql 表格就按照我们刚才转换的表格来转换成MySQL数据 在MySQL数据库中创建数据库&#xff0c;这个根据自身情况。我就在现有test库中测试了。 根据以上步骤&#xff0c;新建转换。 构建流程图&#xff0c;选择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支持的存储数的格式主要有&#xff1a;TEXTFILE&#xff08;行式存储&#xff09; 、SEQUENCEFILE(行式存储)、ORC&…...

Makefile、Make和CMake:构建工具的三剑客

目录 1. Makefile 2. Make 3. CMake Makefile、Make、CMake的关系 在软件开发中&#xff0c;构建工具是必不可少的。它们帮助开发者自动化编译、链接和打包的过程&#xff0c;确保代码能够高效地转化为可执行文件。Makefile、Make和CMake是三个常见的构建工具&#xff0c;它…...

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&#xff0c;www 2025. 文章目录 Sequence Generation Modeling for Continuous Value Prediction核心思想1. CVP常规方法是怎么做的&#xff1f;2. 观看时长预测和CVP是如何关…...

并发编程1

JAVA线程回顾 多线程 多个并行的线程来完成个自的任务&#xff0c;优点是程序响应速度更快&#xff0c;程序性能得到提升。 并行执行与并发执行 并发执行就是在单核CPU下&#xff0c;现成实际上是串行执行的&#xff0c;任务调度器将cpu的时间片分给不同的线程使用&#xff0…...

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 迁移学习的应用场景 二、领域自适应&#xff08;Domain Adaptation&#xff09; 2.1 领域自适应的定义 2.2 领域自适应的挑战 2.3 领域自适应的核心方法 &#…...

WebRTC与PJSIP:呼叫中心系统技术选型指南

助力企业构建高效、灵活的通信解决方案 在数字化时代&#xff0c;呼叫中心系统的技术选型直接影响客户服务效率和业务扩展能力。WebRTC与PJSIP作为两大主流通信技术&#xff0c;各有其核心优势与适用场景。本文从功能、成本、开发门槛等维度为您深度解析&#xff0c;助您精准匹…...

使用IDEA如何隐藏文件或文件夹

选择file -> settings 选择Editor -> File Types ->Ignored Files and Folders (忽略文件和目录) 点击号就可以指定想要隐藏的文件或文件夹...

【人工智能】数据挖掘与应用题库(1-100)

1、涉及变化快慢的问题可以考虑使用导数来分析。 答案:对 2、导数的几何意义是曲线在某点处切线的斜率。 答案:对 3、函数在某点的左导数存在,则导数就存在。 答案:错 4、关于梯度下降算法,下列说法错误的是( ) 错误:梯度下降算法能找到函数精确的最小值。 5、正…...

腾讯云大模型知识引擎驱动的DeepSeek满血版医疗顾问大模型搭建实战

文章目录 1. 引言2. 什么是腾讯云大模型知识引擎&#xff08;LKE&#xff09;&#xff1f;核心优势功能特点应用场景 3. 模型搭建过程3.1 注册登录产品3.2 创建应用3.3 配置模型3.4 配置角色指令3.5 配置欢迎语3.6 配置知识库3.7 配置工作流3.8 启用联网搜索3.9 发布模型 4. 问…...

大白话页面加载速度优化的工具与实践案例

大白话页面加载速度优化的工具与实践案例 优化工具 Chrome开发者工具&#xff1a;这是个超好用的浏览器自带工具。就像你给车做检查的一套工具一样&#xff0c;能帮你查看页面加载的各种情况。比如说&#xff0c;你能在“Network”&#xff08;网络&#xff09;选项里看到每个…...

【JAVA面试题】什么是面向对象?谈谈你对面向对象的理解。

【JAVA面试题】什么是面向对象&#xff1f;谈谈你对面向对象的理解 在 Java 面试中&#xff0c;面向对象 是一个高频考点。它不仅是一种编程思想&#xff0c;更是现代软件开发的核心方法论。本文将从 面向对象的概念、与面向过程的对比、以及 面向对象的三大特性&#xff08;封…...

解锁责任链模式:Java 实战与应用探秘

系列文章目录 后续补充~~~ 文章目录 一、责任链模式基础入门1.1 责任链模式的定义1.2 核心角色剖析1.2.1 抽象处理者&#xff08;Handler&#xff09;1.2.2 具体处理者&#xff08;ConcreteHandler&#xff09;1.2.3 客户端&#xff08;Client&#xff09; 1.3 类图结构展示 二…...

华为 Open Gauss 数据库在 Spring Boot 中使用 Flyway

db-migration&#xff1a;Flyway、Liquibase 扩展支持达梦&#xff08;DM&#xff09;、南大通用&#xff08;GBase 8s&#xff09;、OpenGauss 等国产数据库。部分数据库直接支持 Flowable 工作流。 开源代码仓库 Github&#xff1a;https://github.com/mengweijin/db-migrat…...

汽车电子电控软件开发中因复杂度提升导致的架构恶化问题

针对汽车电子电控软件开发中因复杂度提升导致的架构恶化问题&#xff0c;建议从以下方向进行架构优化和开发流程升级&#xff0c;以提升灵活性、可维护性和扩展性&#xff1a; 一、架构设计与模块化优化 分层架构与模块解耦 采用AUTOSAR标准的分层架构&#xff08;应用层、运行…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

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

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...