深入解析 ArrayList 源码:从动态扩容到高效存取的秘密

全文目录:

    • 开篇语
    • 目录
    • 🌟 前言
    • 🧩 ArrayList 概述
    • 🏗️ ArrayList 的底层实现
      • 📐 构造函数详解
      • 🏗️ 数组的动态扩容机制
    • ⚙️ 核心方法源码解析
      • ➕ `add()` 方法的实现
      • ➖ `remove()` 方法的实现
      • 🔍 `get()` 和 `set()` 方法
    • 🌱 ArrayList 的优缺点分析
      • 优点
      • 缺点
    • 🧠 ArrayList 的适用场景
    • 📝 结语
    • 文末

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

目录

  • 🌟 前言
  • 🧩 ArrayList 概述
  • 🏗️ ArrayList 的底层实现
    • 📐 构造函数详解
    • 🏗️ 数组的动态扩容机制
  • ⚙️ 核心方法源码解析
    • add() 方法的实现
    • remove() 方法的实现
    • 🔍 get()set() 方法
  • 🌱 ArrayList 的优缺点分析
  • 🧠 ArrayList 的适用场景
  • 📝 结语

🌟 前言

嗨,Java 的小伙伴们!提到集合类,你会想到什么?相信很多人脱口而出的就是 ArrayList。作为 Java 集合框架中的明星,ArrayList 因其简单易用、存取效率高、可动态扩容等特点,成为我们开发中常用的数据结构之一。可是,背后的实现到底如何?今天我们就带着好奇心,深入挖掘 ArrayList 源码,解锁它“魔法”般高效的秘密。


🧩 ArrayList 概述

在正式进入源码解析之前,先来个快速回顾。ArrayListList 接口的实现类,本质上是一个基于动态数组的数据结构。它在内存中分配一块连续的空间,用于存储对象引用。当存储元素超过初始容量时,会自动扩容。这种机制使得它可以高效地支持随机存取和动态调整大小,非常适合于大多数需要频繁访问和追加元素的场景。


🏗️ ArrayList 的底层实现

📐 构造函数详解

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);}
}public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);} else {this.elementData = EMPTY_ELEMENTDATA;}
}
  • 无参构造函数:默认初始化一个空数组,等到添加元素时才扩展到默认容量。
  • 指定初始容量的构造函数:允许用户指定初始容量,避免频繁扩容导致的性能开销。
  • 集合构造函数:使用现有集合创建 ArrayList,便于将其他集合转为 ArrayList

🏗️ 数组的动态扩容机制

ArrayList 的关键特性就是“自动扩容”。当现有的数组空间不足以容纳新元素时,它会自动增加容量。默认情况下,每次扩容都会把数组大小增加为原来的 1.5 倍(即 newCapacity = oldCapacity + (oldCapacity >> 1))。

private void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容为1.5倍if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);elementData = Arrays.copyOf(elementData, newCapacity);
}

这样做的好处是减少了数组扩容的次数,提升了性能。不过,扩容过程会涉及数组复制操作,因此在频繁增加大量元素的场景下,合理设置初始容量尤为重要。


⚙️ 核心方法源码解析

add() 方法的实现

ArrayListadd() 方法用于向集合中追加元素。它会先判断容量是否够用,如果不够用,就会调用 grow() 方法扩容。

public boolean add(E e) {ensureCapacityInternal(size + 1);  // 确保容量足够elementData[size++] = e;return true;
}

这里可以看到,add() 方法的逻辑非常简洁清晰。检查容量后,将元素存入 elementData 数组,随后更新 size 大小。

remove() 方法的实现

remove() 方法用于删除指定索引的元素。移除操作会造成元素“空洞”,所以 ArrayList 会将删除位置之后的元素向前移动,填补空缺。

public E remove(int index) {rangeCheck(index);E oldValue = elementData(index);int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index, numMoved);elementData[--size] = null;return oldValue;
}

从上面可以看出,remove() 方法的效率在删除末尾元素时较高,因为无需数组拷贝。然而,当删除位置较靠前时,移位操作的开销就会增大。对于这种情况,可以考虑 LinkedList 等链表结构。

🔍 get()set() 方法

get()set() 方法是 ArrayList 的读写操作,基于索引快速访问元素,非常高效。

public E get(int index) {rangeCheck(index);return elementData(index);
}public E set(int index, E element) {rangeCheck(index);E oldValue = elementData(index);elementData[index] = element;return oldValue;
}

get() 方法通过索引直接定位到对应的元素,这也是 ArrayList 的优势之一。


🌱 ArrayList 的优缺点分析

优点

  1. 快速随机访问:基于数组实现,可以通过索引高效地访问元素。
  2. 动态扩容:容量不足时自动扩展,避免手动管理数组大小。
  3. 实现简洁ArrayList 的大部分操作都很直接,适合大部分场景。

缺点

  1. 插入和删除性能较低:尤其是在头部和中间位置操作时,可能需要大量移位操作。
  2. 内存浪费:扩容机制可能导致内存浪费,特别是数据量波动较大的情况下。

🧠 ArrayList 的适用场景

根据 ArrayList 的特点,它适合以下应用场景:

  • 需要快速随机访问的场景,例如通过索引频繁获取数据的应用。
  • 数据量较小且变化不大的集合。
  • 追加读取操作频繁的应用,但不适合在中间位置频繁插入或删除的情况。

📝 结语

ArrayList 的源码实现展现了 Java 集合框架的设计之美。从构造函数到核心方法,我们看到了一个基于数组的动态数据结构如何通过扩容、移位等操作,平衡了效率和易用性。在实际开发中,选择集合类型时可以根据具体场景的需求来判断 ArrayList 是否为最佳选择。希望通过这篇解析,你能更加得心应手地使用 ArrayList,更深入地理解 Java 集合框架的实现原理!

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/887495.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Amazon AWS公司介绍

Amazon Web Services&#xff08;AWS&#xff09;是亚马逊公司&#xff08;Amazon&#xff09;的子公司&#xff0c;提供广泛的云计算服务&#xff0c;包括弹性计算、存储解决方案、数据库服务、机器学习、物联网&#xff08;IoT&#xff09;和企业应用等。以下是AWS的一些关键…

精密工装夹具加工:打造高精度产品

在现代制造业中&#xff0c;精密工装夹具加工扮演着关键角色&#xff0c;是打造高精度产品不可缺少的环节。 精密工装夹具的设计与制造&#xff0c;首先依赖于对加工工艺的深入理解与精准把握。工程师们需要根据待加工产品的形状、尺寸、精度要求以及加工设备的特性&#xff0c…

使用client-go在命令空间test里面对pod进行操作

目录 一、获取使用restApi调用的token信息 二、client-go操作pod示例 1、获取到客户端 2、创建pod 3、获取test命令空间的所有pod 4、获取某个具体pod的详细信息 5、更新pod 6、删除pod 三、总结 官方参考地址&#xff1a;https://kubernetes.io/docs/reference/kuber…

C++ 优先算法 —— 无重复字符的最长子串(滑动窗口)

目录 题目&#xff1a; 无重复字符的最长子串 1. 题目解析 2. 算法原理 Ⅰ. 暴力枚举 Ⅱ. 滑动窗口&#xff08;同向双指针&#xff09; 3. 代码实现 Ⅰ. 暴力枚举 Ⅱ. 滑动窗口 题目&#xff1a; 无重复字符的最长子串 1. 题目解析 题目截图&#xff1a; 此题所说的…

huggingface使用

import warnings warnings.filterwarnings("ignore") from transformers import pipeline#用人家设计好的流程完成一些简单的任务 classifier pipeline("sentiment-analysis") classifier( [ "Ive been waiting for a HuggingFace cours…

qt 读写文本、xml文件

写txt文件 QString fileName ui->lineEdit->text(); QString fileContent ui->textEdit->toPlainText(); qDebug()<<"test:"<<fileContent; QFile file(fileName); if(!file.open(QFile::WriteOnly|QFile::Text)) { …

第六届机器人、智能控制与人工智能国际(RICAI 2024)

会议信息 会议时间与地点&#xff1a;2024年12月6-8日&#xff0c;中国南京 会议官网&#xff1a;www.ic-ricai.org &#xff08;点击了解大会参会等详细内容&#xff09; 会议简介 第六届机器人、智能控制与人工智能国际学术会议&#xff08;RICAI 2024&#xff09;将于20…

【设计模式】创建型模式之单例模式(饿汉式 懒汉式 Golang实现)

定义 一个类只允许创建一个对象或实例&#xff0c;而且自行实例化并向整个系统提供该实例&#xff0c;这个类就是一个单例类&#xff0c;它提供全局访问的方法。这种设计模式叫单例设计模式&#xff0c;简称单例模式。 单例模式的要点&#xff1a; 某个类只能有一个实例必须…

C++11特性(详解)

目录 1.C11简介 2.列表初始化 3.声明 1.auto 2.decltype 3.nullptr 4.范围for循环 5.智能指针 6.STL的一些变化 7.右值引用和移动语义 1.左值引用和右值引用 2.左值引用和右值引用的比较 3.右值引用的使用场景和意义 4.右值引用引用左值及其一些更深入的使用场景分…

C++-右值引用和移动构造

目录 1. 两种引用方式: 1.1 左值引用&#xff1a; 1.2右值引用 1.3如何判断左右值&#xff1a; 1.4左值引用与右值引用比较 2. 浅拷贝、深拷贝 3.1右值引用的意义&#xff1a; 函数参数传递 函数返还值传递 万能引用 引用折叠 完美转发 std::forward &#x1f33c;&…

React-useState的使用

useState 是 React 提供的一个 Hook&#xff0c;允许你在函数组件中添加和管理状态&#xff08;state&#xff09;。在类组件中&#xff0c;状态管理通常是通过 this.state 和 this.setState 来实现的&#xff0c;而在函数组件中&#xff0c;useState 提供了类似的功能。 基本…

嵌入式硬件设计:从概念到实现的全流程

嵌入式硬件设计是现代电子技术中一个至关重要的领域&#xff0c;涉及从硬件架构设计到硬件调试的各个方面。它为我们日常生活中的各类智能设备、家电、工业控制系统等提供了强大的支持。本文将介绍嵌入式硬件设计的基本流程、关键技术、常用工具以及常见的挑战和解决方案&#…

新能源汽车充电插口类型识别-YOLO标记,可识别Type1,ccs2的充电标准

前言: CCS标准定义的Type-2 CCS汽车充电端口&#xff0c;右侧装有直流充电枪的插头。汽车的充电端口设计巧妙地将交流部分&#xff08;上半部分&#xff09;与直流部分&#xff08;下半部分的两个粗大的接口&#xff09;集于一体。在交流和直流充电过程中&#xff0c;电动汽车…

Pytest使用Jpype调用jar包报错:Windows fatal exception: access violation

问题描述 ​   之前我们有讲过如何使用Jpype调用jar包&#xff0c;在成功调用jar包后&#xff0c;接着在Pytest框架下编写自动测试用例。但是在Pytest下使用Jpype加载jar包&#xff0c;并调用其中的方法会以下提示信息&#xff1a; ​   虽然提示信息显示有Windows显示致命…

Netty基本原理

目录 前言 原生NIO VS Netty 原生NIO存在的问题 Netty的优点 线程模型 传统阻塞 I/O (Blocking I/O) 2. 非阻塞 I/O (Non-blocking I/O) 3. 多路复用 I/O (Multiplexed I/O) 4. Reactor 模式 常见的 Reactor 模式的变体&#xff1a; Netty线程模型 工作原理 前言 N…

MySQL系列之数据类型(Numeric)

导览 前言一、数值类型综述二、数值类型详解1. NUMERIC1.1 UNSIGNED或SIGNED1.2 数据类型划分 2. Integer类型取值和存储要求3. Fixed-Point类型取值和存储要求4. Floating-Point类型取值和存储要求 结语精彩回放 前言 MySQL系列最近三篇均关注了和我们日常工作或学习密切相关…

一学就废|Python基础碎片,格式化F-string

Python 3.6 中引入了 f-string语法&#xff0c;提供了一种简洁直观的方法来将表达式和变量直接嵌入到字符串中进行字符串格式化&#xff0c;f -string背后的想法是使字符串插值更简单。 要创建 f -string&#xff0c;在字符串前加上字母 “f”即可&#xff0c;与字符串本身的格…

在 Mac(ARM 架构)上安装 JDK 8 环境

文章目录 步骤 1&#xff1a;检查系统版本步骤 2&#xff1a;下载支持 ARM 的 JDK 8步骤 3&#xff1a;安装 JDK步骤 4&#xff1a;配置环境变量步骤 5&#xff1a;验证安装步骤 6&#xff1a;注意事项步骤7&#xff1a;查看Java的安装路径 在 Mac&#xff08;ARM 架构&#xf…

Python设计模式详解之15 ——迭代器模式

Python 中的 Iterator&#xff08;迭代器&#xff09;设计模式 是一种行为型设计模式&#xff0c;用于逐一访问集合对象中的元素而不暴露其底层实现。Python 本身对迭代器模式提供了良好的支持&#xff0c;迭代器通常通过 __iter__ 和 __next__ 方法实现。 迭代器模式的组成 迭…

11.27周三F34-Day8打卡

文章目录 1. 学习让我感觉很棒。(什么关系?动作 or 描述?主语部分是?)解析答案:【解析答案分析】【对比分析】【拓展内容】2. 她忽然想起来钥匙放另一个包里了。解析答案:【拓展内容】3. 她来不来都没关系。(该由什么引导?这句话又属于什么关系,动作 or 描述?)解析答案…