Java基础——集合进阶3

一、ArrayList

1.1 什么是 ArrayList?

ArrayList 是 Java 集合框架中 List 接口的一个 基于动态数组实现的可变长列表

✅ 核心定义:

  • 实现了 ListRandomAccess(支持快速随机访问)、CloneableSerializable 接口
  • 底层使用 Object[] 数组存储元素
  • 线程不安全(非同步)
  • 允许存储 null 值,且允许多个 null

自然Collection和List的所有方法实现类ArrayList也可以用。

1.2 ArrayList 的作用与适用场景

主要作用:

  • 提供一个长度可自动增长的有序容器,用于存储和操作一组对象
  • 支持通过索引快速访问、修改、插入、删除元素

✅ 适用场景(高频使用):

  • 需要频繁通过索引访问元素(如 get(i)
  • 元素数量大致已知或变化不大
  • 主要操作是遍历、读取、末尾添加
  • 不需要线程安全(单线程环境)

💡 "90% 的 List 场景,首选 ArrayList!"

1.3 常用方法与代码示例

方法 说明 时间复杂度
add(E e) 在末尾添加元素 O(1)(均摊)
add(int index, E e) 在指定位置插入 O(n)(需移动后续元素)
get(int index) 获取指定索引元素 O(1)
set(int index, E e) 替换指定位置元素 O(1)
remove(int index) 删除指定索引元素 O(n)
remove(Object o) 删除第一个匹配的元素 O(n)
size() 返回元素个数 O(1)
isEmpty() 是否为空 O(1)
contains(Object o) 是否包含某元素 O(n)
indexOf(Object o) 返回首次出现的索引 O(n)
clear() 清空所有元素 O(1)(仅置 null,不释放数组)
java 复制代码
import java.util.*;

public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        // 添加
        list.add("Apple");
        list.add("Banana");
        list.add(1, "Cherry"); // 插入到索引1

        // 访问
        System.out.println(list.get(0)); // Apple
        System.out.println(list.size()); // 3

        // 修改
        list.set(0, "Apricot");

        // 删除
        list.remove("Banana"); // 删除值
        list.remove(1);        // 删除索引1

        // 遍历
        list.forEach(System.out::println);
    }
}

1.4 ArrayList集合的底层原理

1.1.1 扩容机制

addAll()方法:可以一次添加List1整个集合中的内容全都添加到List2中。考虑源码的时候要把一次添加一个元素的情况和一次全部添加的情况都要考虑。

注意:底层创建出数组是在添加第一个元素的时候创建的,不是事先创建的。

size的两层含义:表示元素个数、下次存入的位置。

具体的流程详解:

首先在底层,通过空参构造来创建了一个集合,默认初始化长度为0,添加第一个元素"aaa";此时调用add()方法;

把参数"aaa"传递过去,底层又帮我们调用一个add()方法,其中就有三个参数。

参数一:当前要添加的元素;

参数二:集合底层数组的名字;

参数三:集合的长度/当前元素应该存入的位置。

那么调用的add()方法,把三个参数传递给了我们的形参,这个add()方法当中首先会做一个判断,s即你当前要添加的位置,s == elementData.length 是不是等于当前数组的长度,如果是调用grow()方法,grow()其实就是数组的扩容。

grow()方法:会把现有的个数+1(size+1); 然后再去调用有参的构造方法,此时数组长度就变成了1,传递给grow()方法体时,形参(minCapacity)就等于1。

int oidCapacity = elementData.length 记录原来的旧有容量(即0),那么接下来的判断就不满足走else语句,那么后面还要扩容的话就执行if语句里面的代码

调用了Math.max()比较DEFAULT_CAPACITY (10)与 minminCapacity(1)水大;所以new object默认就是10,层层进行返回,默认数组长度就是10,在传入参数之后才创建。

💡 为什么是 1.5 倍?

  • 避免频繁扩容(空间换时间)
  • 比 2 倍更节省内存(减少内存碎片)

1.5 高频面试题(面经精要)

Q1:ArrayList 的默认初始容量是多少?

:JDK 8+ 中,空参构造器创建的 ArrayList 初始容量为 0 ,第一次 add 时扩容为 10

(注意:不是一开始就分配 10!)


Q2:ArrayList 如何扩容?扩容多少?

:当元素数量超过当前数组长度时,会创建一个 1.5 倍原容量的新数组,并将旧数组元素复制过去。若 1.5 倍仍不足,则直接扩到所需大小。


Q3:为什么 ArrayList 查询快、增删慢?

  • 查询快:底层是数组,支持 O(1) 随机访问
  • 增删慢:插入或删除中间元素时,需调用 System.arraycopy() 移动后续所有元素,时间复杂度 O(n)

声明:

分析借鉴于通义AI

以上均来源于B站@ITheima的教学内容!!!

本人跟着视频内容学习,整理知识引用

相关推荐
xian_wwq2 分钟前
【学习笔记】探讨大模型应用安全建设系列5——供应链安全与数据防护
笔记·学习
就叫_这个吧12 分钟前
Java实现线程间的通讯--使用synchronized关键字和JUC方式实现
java·开发语言
学习中.........18 分钟前
JVM 垃圾回收核心技术、演进全景与生产调优规范
java·jvm·测试工具
小小编程路20 分钟前
C++类作用域
java·jvm·c++
FlyWIHTSKY27 分钟前
Next中引入 Ant Design (antd)的配置
开发语言·前端·javascript
小江的记录本28 分钟前
【Java并发编程】锁机制:volatile:JMM内存模型、可见性/禁止指令重排、内存屏障、单例模式中的应用(附《思维导图》+《面试高频考点清单》)
java·后端·python·mysql·单例模式·面试·职场和发展
zandy101131 分钟前
2026嵌入式BI PaaS平台技术剖析与实现指南
java·运维·paas
csdn小瓯33 分钟前
前端工程化:React + TypeScript + Tailwind CSS 的组件化实践
开发语言·人工智能·python
hef28835 分钟前
R包grafify:简单操作实现高效统计绘图
开发语言·python·r语言
这是谁的博客?35 分钟前
Python 异步编程核心原理与实践深度解析
java·网络·python·协程·asyncio·异步编程