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

Java-List集合类全面解析

Java-List集合类全面解析

  • 前言
  • 一、List接口概述与核心特性
    • 1.1 List在集合框架中的位置
    • 1.2 List的核心特性
    • 1.3 常见实现类对比
  • 二、ArrayList源码剖析与应用场景
    • 2.1 内部结构与初始化
    • 2.2 动态扩容机制
    • 2.3 性能特点与最佳实践
  • 三、LinkedList 源码剖析与应用场景
    • 3.1 内部结构与节点定义
    • 3.2 核心操作实现
    • 3.3 与 ArrayList 的性能对比
  • 四、线程安全的 List 实现
    • 4.1 Vector 的使用与局限性
    • 4.2 CopyOnWriteArrayList 原理
    • 4.3 适用场景对比
  • 五、List 的高级应用技巧
    • 5.1 不可变 List 的创建
    • 5.2 List 的排序操作
    • 5.3 列表转换与过滤(Java 8+)
  • 六、常见问题与解决方案
    • 6.1 并发修改异常(ConcurrentModificationException)
    • 6.2 性能优化建议
  • 七、List 类的典型应用场景
    • 7.1 数据缓存
    • 7.2 任务队列
    • 7.3 线程安全配置中心
  • 总结

前言

Java中集合框架是数据处理的核心工具之一,List作为单列集合Collection的重要子接口,凭借其有序、可重复的特性,成为日常开发中使用频率极高的组件。本文将从基础概念入手,深入剖析List接口及其实现类的内部机制、应用场景与最佳实践,并结合大量代码示例帮助读者全面掌握这一核心知识点。

一、List接口概述与核心特性

1.1 List在集合框架中的位置

Java集合框架主要分为两大体系:单列集合Collection和双列集合MapList作为Collection的直接子接口,继承了Collection的基本操作,并额外提供了基于索引的访问能力。其继承关系如下:

java.lang.Object↳ java.util.Collection<E>↳ java.util.List<E>

1.2 List的核心特性

与其他Collection接口相比,List具有以下显著特点:

  1. 有序性:元素按照插入顺序排列,可以通过索引精确访问

  2. 可重复性:允许存储重复元素

  3. 索引支持:提供基于0的整数索引操作元素

  4. 丰富的操作方法:新增了add(index, element)get(index)remove(index)等索引相关方法

1.3 常见实现类对比

实现类数据结构线程安全特点
ArrayList动态数组随机访问快,插入删除慢,默认容量10,扩容因子1.5
LinkedList双向链表插入删除快,随机访问慢,实现了`Deque`接口
Vector动态数组线程安全但性能较低,扩容因子2
CopyOnWriteArrayList写时复制数组读操作无锁,写操作复制数组,适用于读多写少场景

二、ArrayList源码剖析与应用场景

2.1 内部结构与初始化

ArrayList的核心是一个动态扩容的Object数组:

transient Object[] elementData; // 存储元素的数组
private int size; // 实际元素数量

初始化时可指定初始容量:

// 默认构造器,初始为空数组,首次添加元素时扩容为10
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}// 指定初始容量
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];}
}

2.2 动态扩容机制

当元素数量超过数组容量时,会触发扩容操作:

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);
}

2.3 性能特点与最佳实践

  • 优势场景:频繁随机访问、较少插入删除操作

  • 注意事项

    • 初始容量设置:预计元素数量较大时,建议指定合理初始容量减少扩容次数

    • 避免中间插入删除:此类操作会导致后续元素整体移动,时间复杂度 O (n)

// 示例:预分配容量提高性能
ArrayList<String> list = new ArrayList<>(1000);
for (int i = 0; i < 1000; i++) {list.add("element" + i); // 避免多次扩容
}

三、LinkedList 源码剖析与应用场景

3.1 内部结构与节点定义

LinkedList 基于双向链表实现,每个节点包含前驱和后继引用:

private static class Node<E> {E item;Node<E> next;Node<E> prev;Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}
}

3.2 核心操作实现

插入操作仅需修改前后节点引用:

// 在指定位置插入元素
void linkBefore(E e, Node<E> succ) {final Node<E> pred = succ.prev;final Node<E> newNode = new Node<>(pred, e, succ);succ.prev = newNode;if (pred == null)first = newNode;elsepred.next = newNode;size++;modCount++;
}

3.3 与 ArrayList 的性能对比

操作类型 ArrayList 时间复杂度 LinkedList 时间复杂度
随机访问 get (i) O(1) O(n)
尾部插入 add (e) O (1)(可能扩容) O(1)
中间插入 add (i,e) O (n)(元素移动) O (n/2)(定位节点)
删除指定元素 remove (e) O (n)(查找 + 移动) O (n)(查找)

四、线程安全的 List 实现

4.1 Vector 的使用与局限性

Vector 是早期的线程安全 List 实现,所有公共方法都使用synchronized修饰:

public synchronized E get(int index) {if (index >= elementCount)throw new ArrayIndexOutOfBoundsException(index);return elementData(index);
}

但这种粗粒度同步导致性能较差,现代开发中已较少使用。

4.2 CopyOnWriteArrayList 原理

采用写时复制策略,写操作会创建新数组:

public boolean add(E e) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}
}

4.3 适用场景对比

  • Vector:适用于遗留系统,需要全面线程安全保证

  • CopyOnWriteArrayList:适用于读多写少场景,如配置中心、事件监听器列表

五、List 的高级应用技巧

5.1 不可变 List 的创建

使用Collections.unmodifiableList或 Java 9 + 的List.of创建不可变列表:

// Java 9+
List<String> immutableList = List.of("a", "b", "c");// 基于现有列表创建
List<String> original = new ArrayList<>();
List<String> unmodifiable = Collections.unmodifiableList(original);

5.2 List 的排序操作

使用Collections.sortList.sort方法:

// 自然排序
list.sort(Comparator.naturalOrder());// 自定义排序
list.sort((e1, e2) -> e1.getName().compareTo(e2.getName()));

5.3 列表转换与过滤(Java 8+)

利用 Stream API 进行转换和过滤:

List<String> names = people.stream().filter(p -> p.getAge() > 18).map(Person::getName).collect(Collectors.toList());

六、常见问题与解决方案

6.1 并发修改异常(ConcurrentModificationException)

在使用迭代器遍历 List 时修改结构会抛出此异常,解决方案:

  • 使用Iterator.remove()方法

  • 使用CopyOnWriteArrayList

  • 使用 for 循环倒序遍历

// 安全删除示例
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {String item = it.next();if (condition) {it.remove(); // 安全删除}
}

6.2 性能优化建议

  • 对于 ArrayList,预估容量避免频繁扩容

  • 避免在 LinkedList 中使用随机访问

  • 批量操作优先使用addAll而非循环添加

七、List 类的典型应用场景

7.1 数据缓存

使用 ArrayList 存储热点数据,利用其快速随机访问特性:

public class DataCache {private final List<Data> cache = new ArrayList<>();public Data getById(int id) {return cache.get(id); // O(1)访问}
}

7.2 任务队列

使用 LinkedList 实现 FIFO 队列:

public class TaskQueue {private final LinkedList<Runnable> queue = new LinkedList<>();public synchronized void enqueue(Runnable task) {queue.addLast(task);}public synchronized Runnable dequeue() {return queue.pollFirst();}
}

7.3 线程安全配置中心

使用 CopyOnWriteArrayList 存储配置项:

public class ConfigCenter {private final CopyOnWriteArrayList<ConfigItem> configs = new CopyOnWriteArrayList<>();public void addConfig(ConfigItem item) {configs.add(item); // 写操作线程安全}public List<ConfigItem> getAllConfigs() {return new ArrayList<>(configs); // 读操作无锁}
}

总结

根据情况选择合适的 List 实现

  • 需要快速随机访问:ArrayList

  • 需要频繁插入删除:LinkedList

  • 需要线程安全:CopyOnWriteArrayList(读多写少)或 Vector(全同步)

通过深入理解 List 接口及其实现类的内部机制和应用场景,我们可以更加高效地使用这一核心工具,编写出性能优异、结构清晰的代码。希望本文能够帮助读者全面掌握 Java List 类的使用技巧,在实际开发中发挥更大的价值。

若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ

相关文章:

Java-List集合类全面解析

Java-List集合类全面解析 前言一、List接口概述与核心特性1.1 List在集合框架中的位置1.2 List的核心特性1.3 常见实现类对比 二、ArrayList源码剖析与应用场景2.1 内部结构与初始化2.2 动态扩容机制2.3 性能特点与最佳实践 三、LinkedList 源码剖析与应用场景3.1 内部结构与节…...

uniapp-商城-60-后台 新增商品(属性的选中和页面显示,数组join 的使用)

前面添加了属性&#xff0c;添加属性的子级项目。也分析了如何回显&#xff0c;但是在添加新的商品的时&#xff0c;我们也同样需要进行选择&#xff0c;还要能正常的显示在界面上。下面对页面的显示进行分析。 1、界面情况回顾 属性显示其实是个一嵌套的数据显示。 2、选中的…...

[c语言日寄]数据结构:栈

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…...

WEB安全--Java安全--LazyMap_CC1利用链

一、前言 该篇是基于WEB安全--Java安全--CC1利用链-CSDN博客的补充&#xff0c;上篇文章利用的是TransformedMap类&#xff0c;而CC链的原作者是利用的LazyMap类作为介质进行的触发。 所以本文将分析国外原作者在ysoserial commonscollections1中给出的CC1利用链。 二、回顾梳…...

【杂谈】-AI 重塑体育营销:从内容管理到创意释放的全面变革

AI 重塑体育营销&#xff1a;从内容管理到创意释放的全面变革 文章目录 AI 重塑体育营销&#xff1a;从内容管理到创意释放的全面变革1、加速从采集到推广的内容生命周期2、个性化粉丝体验3、以比赛速度分发体育内容4、让创作者在人工智能&#xff08;AI&#xff09;时代自由创…...

黑马k8s(六)

1.Deployment&#xff08;Pod控制器&#xff09; Selector runnginx 标签选择&#xff1a;会找pod打的标签 执行删除之后&#xff0c;pod也会删除&#xff0c;Terminating正在删除 如果想要访问其中的一个pod借助&#xff1a;IP地址端口号访问 假设在某一个瞬间&#xff0c;…...

【数据结构】二分查找(返回插入点)5.14

二分查找基础版 package 二分查找; public class BinarySearch { public static void main(String[] args) { // TODO Auto-generated method stub } public static int binarySearchBasic(int[] a,int target) { int i0,ja.length-1; //设置指针初值 while…...

如何设计一个二级缓存(Redis+Caffeine)架构?Redis 6.0多线程模型如何工作?

一、二级缓存&#xff08;RedisCaffeine&#xff09;架构设计 1. 设计目标 通过「本地缓存&#xff08;Caffeine&#xff09; 分布式缓存&#xff08;Redis&#xff09;」的分层结构&#xff0c;实现&#xff1a; 低延迟&#xff1a;热点数据本地缓存&#xff08;内存级访问…...

Java:logback-classic与slf4j版本对应关系

1、结论 logback-classic-1.2.x及以下版本&#xff0c;则适配的slf4j 1.0.x - 1.7.x logback-classic-1.3.x及以上版本&#xff0c;则适配的slf4j 1.8.x及以上 2、原因分析 &#xff08;1&#xff09;logback-classic-1.2.x及以下版本 通过org.slf4j.impl.StaticLoggerBinder初…...

【OpenGL学习】(一)创建窗口

文章目录 【OpenGL学习】&#xff08;一&#xff09;创建窗口 【OpenGL学习】&#xff08;一&#xff09;创建窗口 GLFW OpenGL 本身只是一套图形渲染 API&#xff0c;不提供窗口创建、上下文管理或输入处理的功能。 GLFW 是一个支持创建窗口、处理键盘鼠标输入和管理 OpenGL…...

AI大语言模型评测体系演进与未来展望

随着人工智能技术的飞速发展,大语言模型(LLMs)已成为自然语言处理领域的核心研究方向。2025年最新行业报告显示,当前主流模型的评测体系已从单一任务评估转向多维度、全链路的能力剖析。例如,《全球首个大语言模型意识水平”识商”白盒DIKWP测评报告》通过数据、信息、知识…...

微服务项目->在线oj系统(Java版 - 5)

相信自己,终会成功 微服务代码: lyyy-oj: 微服务 目录 C端代码 用户题目接口 修改后用户提交代码(应用版) 用户提交题目判题结果 代码沙箱 1. 代码沙箱的核心功能 2. 常见的代码沙箱实现方式 3. 代码沙箱的关键问题与解决方案 4. 你的代码如何与沙箱交互&#xff1f; …...

disryptor和rabbitmq

disryptor和rabbitmq Disruptor 是什么&#xff1f; Disruptor 是一个由 LMAX Exchange 开发的高性能、低延迟的进程内&#xff08;in-process&#xff09;并发编程框架/库。它最初是为了解决金融交易系统中高吞吐量、低延迟消息传递的需求而设计的。 核心特点和设计理念&am…...

HTTP与HTTPS协议的核心区别

HTTP与HTTPS协议的核心区别 数据传输安全性 HTTP采用明文传输&#xff0c;数据易被窃听或篡改&#xff08;如登录密码、支付信息&#xff09;&#xff0c;而HTTPS通过SSL/TLS协议对传输内容加密&#xff0c;确保数据完整性并防止中间人攻击。例如&#xff0c;HTTPS会生成对称加…...

Flink 并行度的设置

在 Apache Flink 中&#xff0c;并行度&#xff08;Parallelism&#xff09; 是控制任务并发执行的核心参数之一。Flink 提供了 多个层级设置并行度的方式&#xff0c;优先级从高到低如下&#xff1a; &#x1f9e9; 一、Flink 并行度的四个设置层级 层级描述设置方式Operator…...

【微服务】SpringBoot + Docker 实现微服务容器多节点负载均衡详解

目录 一、前言 二、前置准备 2.1 基本环境 2.2 准备一个springboot工程 2.2.1 准备几个测试接口 2.3 准备Dockerfile文件 2.4 打包上传到服务器 三、制作微服务镜像与运行服务镜像 3.1 拷贝Dockerfile文件到服务器 3.2 制作服务镜像 3.3 启动镜像服务 3.4 访问一下服…...

get请求使用数组进行传参

get请求使用数组进行传参,无需添加中括号 mvc接口要添加参数名&#xff0c;使用array承接。不能用list, 否则会报错 这里是用apifox模拟前端调用。 前端调用代码 // 根据项目ID和角色ID查询相关审批人 export function findRelativeApproverByProjectIdAndRoleId(roleIds, p…...

20. 自动化测试框架开发之Excel配置文件的IO开发

20.自动化测试框架开发之Excel配置文件的IO开发 一、核心架构解析 1.1 类继承体系 class File: # 文件基类# 基础文件验证和路径管理class ExcelReader(File): # Excel读取器# 实现Excel数据解析逻辑1.2 版本依赖说明 # 必须安装1.2.0版本&#xff08;支持xlsx格式&#…...

【MySQL成神之路】MySQL常用语法总结

目录 MySQL 语法总结 数据库操作 表操作 数据操作 查询语句 索引操作 约束 事务控制 视图操作 存储过程和函数 触发器 用户和权限管理 数据库操作 创建数据库&#xff1a; CREATE DATABASE database_name; 选择数据库&#xff1a; USE database_name; 删除数…...

Linux动静态库制作与原理

什么是库 库是写好的现有的&#xff0c;成熟的&#xff0c;可以复用的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个人的代码都从零开始&#xff0c;因此库的存在意义非同寻常。 本质上来说库是一种可执行代码的二进制形式&#xff0c;可以被操作系统…...

确保高质量的音视频通话,如何最大化利用视频带宽

在当今数字时代&#xff0c;音视频内容随处可见&#xff0c;对于开发者来说&#xff0c;理解互联网带宽变得至关重要。我们的在线体验质量&#xff0c;无论是观看高清电影还是演唱会直播&#xff0c;都严重依赖于互联网带宽的概念。在本文中&#xff0c;我们将揭示视频带宽的复…...

ffmpeg 把一个视频复制3次

1. 起因&#xff0c; 目的: 前面我写过&#xff0c;使用 python 把一个视频复制3次但是速度太慢了&#xff0c;我想试试看能否改进。而且我想换一种新的视频处理思路&#xff0c;并试试看速度如何。 2. 先看效果 效果就是能行&#xff0c;而且速度也快。 3. 过程: 代码 1…...

GPT/Claude3国内免费镜像站更新 亲测可用

无限次使用&#xff1a;无限制的提问次数&#xff0c;不设上限&#xff0c;随心所欲。 无需魔法、稳定流畅&#xff1a;操作简便&#xff0c;无需复杂设置&#xff0c;即可享受稳定流畅的服务。 手机和电脑均能用&#xff1a;轻松适配手机和电脑&#xff0c;使用体验更佳。 …...

AI自动化工作流:开启当下智能生产力的价值

举手之言&#xff1a;AI自动化工作流创造了什么呢&#xff1f; AI自动化工作流 &#xff0c;顾名思义&#xff0c;是将人工智能&#xff08;AI&#xff09;技术与自动化流程相结合&#xff0c;通过智能化的方式来完成复杂的任务和操作。简单来说&#xff0c;它就是利用AI的强大…...

stm32——EXTI外部中断

NVIC优先级分组 抢占优先级 可以进行中断嵌套的优先级&#xff0c;即可以不等上一个中断执行完成就进入下一个中断 响应优先级 决定中断发生的顺序&#xff0c;但不可嵌套 程序实现 对射式红外传感计次 #include "stm32f10x.h" // Device head…...

Python:操作Excel按行写入

Python按行写入Excel数据,5种实用方法大揭秘! 在日常的数据处理和分析工作中,我们经常需要将数据写入到Excel文件中。Python作为一门强大的编程语言,提供了多种库和方法来实现将数据按行写入Excel文件的功能。本文将详细介绍5种常见的Python按行写入Excel数据的方法,并附上…...

Redis进阶知识

Redis 1.事务2. 主从复制2.1 如何启动多个Redis服务器2.2 监控主从节点的状态2.3 断开主从复制关系2.4 额外注意2.5拓扑结构2.6 复制过程2.6.1 数据同步 3.哨兵选举原理注意事项 4.集群4.1 数据分片算法4.2 故障检测 5. 缓存5.1 缓存问题 6. 分布式锁 1.事务 Redis的事务只能保…...

Python机器学习笔记(二十三 模型评估与改进-网格搜索)

上一次学习了评估一个模型的泛化能力,现在继续学习通过调参来提升模型的泛化性能。scikit-learn中许多算法的参数设置,在尝试调参之前,重要的是要理解参数的含义。找到一个模型的重要参数(提供最佳泛化性能的参数)的取值是一项棘手的任务,但对于几乎所有模型和数据集来说…...

12.vue整合springboot首页显示数据库表-实现按钮:【添加修改删除查询】

vue整合springboot首页显示数据库表&#xff1a;【添加修改删除查询】 提示&#xff1a;帮帮志会陆续更新非常多的IT技术知识&#xff0c;希望分享的内容对您有用。本章分享的是node.js和vue的使用。前后每一小节的内容是存在的有&#xff1a;学习and理解的关联性。【帮帮志系…...

bisheng系列(一)- 本地部署(Docker)

目录 一、导读 二、说明 1、镜像说明 2、本节内容 三、docker部署 1、克隆代码 2、运行镜像 3、可能的错误信息 四、页面测试 1、注册用户 2、登陆成功 3、添加模型 一、导读 环境&#xff1a;Ubuntu 24.04、Windows 11、WSL 2、Python 3.10 、bisheng 1.1.1 背景…...