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

Java ArrayList 完整详解

Java ArrayList 完整详解

一、概述

ArrayListjava.util包下基于动态数组实现的 List 集合,底层是 Object[] 数组,自动扩容,支持随机访问、增删改查。

  • 线程不安全,多线程并发修改会抛ConcurrentModificationException
  • 允许存放null,元素可重复、有序(插入顺序不变)
  • 查询快、中间/头部删除插入慢(需要数组移位)

类关系

ArrayList<E>extendsAbstractList<E>implementsList<E>,RandomAccess,Cloneable,Serializable

RandomAccess标记接口:支持下标快速随机访问,遍历优先用普通for循环。

二、底层原理

  1. 默认初始容量DEFAULT_CAPACITY = 10
  2. 空构造器先赋值空数组,第一次add时才扩容到10,节省内存
  3. 扩容机制
    • 新容量 = 旧容量 + 旧容量 / 2(1.5倍扩容)
    • 若1.5倍仍不够,直接取所需最小容量
    • 最大容量:Integer.MAX_VALUE - 8
  4. 增删操作:数组复制Arrays.copyOf(),移位消耗性能

三、常用构造方法

// 1. 空构造,初始数组为空,首次add扩容至10ArrayList<String>list1=newArrayList<>();// 2. 指定初始容量(推荐已知数据量时使用,减少扩容)ArrayList<Integer>list2=newArrayList<>(20);// 3. 传入集合,复制所有元素List<Integer>temp=Arrays.asList(1,2,3);ArrayList<Integer>list3=newArrayList<>(temp);

四、核心常用API

1. 添加元素

ArrayList<String>list=newArrayList<>();list.add("A");// 尾部添加list.add(1,"B");// 指定下标插入(下标不能越界)list.addAll(Arrays.asList("C","D"));// 批量添加集合

2. 获取元素

Strings=list.get(0);// 根据下标取值,越界抛IndexOutOfBoundsExceptionintsize=list.size();// 获取集合元素个数

3. 修改元素

list.set(0,"AA");// 替换指定下标元素,返回旧值

4. 删除元素

list.remove(0);// 按下标删除,返回被删元素list.remove("B");// 按对象删除,只删第一个匹配元素,返回booleanlist.removeAll(Arrays.asList("C","D"));// 删除交集元素list.clear();// 清空所有元素,数组保留容量

5. 判断与查找

list.contains("A");// 是否包含元素list.indexOf("A");// 首个匹配下标,无则-1list.lastIndexOf("A");// 最后一个匹配下标list.isEmpty();// 是否为空集合

6. 转换数组

Object[]arr1=list.toArray();String[]arr2=list.toArray(newString[0]);// 转指定类型数组

五、三种遍历方式

1. 普通for(推荐,随机访问最快)

for(inti=0;i<list.size();i++){System.out.println(list.get(i));}

2. 增强for循环(foreach,底层迭代器)

for(Stringstr:list){System.out.println(str);}

3. Iterator迭代器(遍历中安全删除)

Iterator<String>it=list.iterator();while(it.hasNext()){Strings=it.next();if("A".equals(s)){it.remove();// 安全删除,不会并发修改异常}}

❌ 禁止foreach里直接list.remove(),会触发并发修改异常。

六、线程安全问题

ArrayList非线程安全,多线程同时读写会报错或数据错乱。

解决方案

  1. Vector:旧集合,方法全加synchronized,性能差,不推荐
  2. Collections.synchronizedList():包装成同步集合
List<String>safeList=Collections.synchronizedList(newArrayList<>());
  1. CopyOnWriteArrayList:读写分离,读不加锁,写复制新数组,读多写少场景首选

七、常用示例代码

importjava.util.ArrayList;importjava.util.Arrays;publicclassArrayListDemo{publicstaticvoidmain(String[]args){ArrayList<Integer>nums=newArrayList<>();// 添加nums.add(10);nums.add(20);nums.add(30);nums.add(1,15);// 查询System.out.println(nums.get(1));// 15System.out.println(nums.size());// 4// 修改nums.set(0,99);// 删除nums.remove(Integer.valueOf(30));// 遍历for(Integernum:nums){System.out.print(num+" ");}}}

八、ArrayList vs LinkedList

特性ArrayListLinkedList
底层动态数组双向链表
查询快 O(1)慢 O(n)
头尾增删尾部快,头部慢头尾极快 O(1)
内存连续数组,占用少每个节点存前后指针,开销大
适用场景大量查询、少量删除频繁头部/中间插入删除

九、常见坑

  1. 下标越界get(i)add(i,obj)i >= size 抛异常
  2. foreach遍历中调用list.remove()→ ConcurrentModificationException,要用迭代器删除
  3. Arrays.asList()返回的集合不能add/remove,底层固定数组,需套new ArrayList<>()
  4. 存储基础类型会自动装箱成包装类(int→Integer)
  5. 扩容会产生大量数组复制,大数据初始化建议指定容量
http://www.jsqmd.com/news/1086193/

相关文章:

  • 逐点融合与运动学增强:Point-LIO如何实现超高带宽激光惯性里程计
  • 对偶上升法:从拉格朗日松弛到分布式优化的梯度之路
  • GetQzonehistory:一键找回丢失的QQ空间青春记忆完整指南
  • 盐城黄金白银回收铂金旧金回收无套路门店 TOP 榜单 实地测评资料整理
  • LLVM IR 优化 Pass 深度剖析:Rust 编译后端的底层机制与性能调优
  • 家庭是一个动态平衡的系统的庖丁解牛
  • 瑞萨RA2A2开发实战:从FSP示例项目到J-Link RTT调试全解析
  • Cadence SPB17.4 Capture CIS 常见错误代码解析与实战排查指南
  • ABAP Open SQL 新语法实战:从常量赋值到内表关联的进阶指南
  • 解锁1490款PS4游戏:GoldHEN金手指管理器的终极体验
  • 从电位器分压到ADC采集:OPA2350UA运放电路的设计与调校
  • VOMAKO「月灰疏影」S2004石英石|把东方禅意装进现代家
  • 从 1G 到 6G,一部“连接”本质的跃迁史
  • 67.等待与回响
  • Echarts Graph关系图实战:从零构建动态企业关系网络
  • 从街头到屏幕:用EasyOCR轻松实现多语言文本提取
  • API接口路径遍历漏洞深度剖析:以CVE-2024-45388为例
  • 终极跨平台体验:PiliPlus B站客户端完全使用指南
  • 终极星露谷物语农场规划器:打造完美虚拟农场的完整指南
  • 雅安黄金白银回收铂金旧金回收无套路门店 TOP 榜单 实地测评资料整理
  • 终极指南:如何用Python自动化脚本轻松搞定B站会员购抢票
  • ANSYS Mechanical边界条件实战:从惯性载荷到热载荷的完整定义与应用
  • 伊春黄金白银回收铂金旧金回收无套路门店 TOP 榜单 实地测评资料整理
  • 大学生如何免费白嫖正版软件?JetBrains、Office、MATLAB教育认证指南
  • 如何通过仿真与匹配网络优化天线隔离度?
  • Vivado功耗报告深度解读:从Report Power到系统级能效优化
  • 终极指南:apt-offline——离线环境下的Debian包管理革命
  • 卫星健康诊断:从关键遥测参数看系统运行状态
  • 战斗部毁伤评估:基于Gurney与Shapiro公式的破片飞散矢量仿真
  • 软考新大纲命题逻辑大起底:基于近5年真题建模的12个高频出题锚点