全文目录:
- 开篇语
- 目录
- 🌟 前言
- 🧩 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 概述
在正式进入源码解析之前,先来个快速回顾。ArrayList
是 List
接口的实现类,本质上是一个基于动态数组的数据结构。它在内存中分配一块连续的空间,用于存储对象引用。当存储元素超过初始容量时,会自动扩容。这种机制使得它可以高效地支持随机存取和动态调整大小,非常适合于大多数需要频繁访问和追加元素的场景。
🏗️ 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()
方法的实现
ArrayList
的 add()
方法用于向集合中追加元素。它会先判断容量是否够用,如果不够用,就会调用 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 的优缺点分析
优点
- 快速随机访问:基于数组实现,可以通过索引高效地访问元素。
- 动态扩容:容量不足时自动扩展,避免手动管理数组大小。
- 实现简洁:
ArrayList
的大部分操作都很直接,适合大部分场景。
缺点
- 插入和删除性能较低:尤其是在头部和中间位置操作时,可能需要大量移位操作。
- 内存浪费:扩容机制可能导致内存浪费,特别是数据量波动较大的情况下。
🧠 ArrayList 的适用场景
根据 ArrayList
的特点,它适合以下应用场景:
- 需要快速随机访问的场景,例如通过索引频繁获取数据的应用。
- 数据量较小且变化不大的集合。
- 追加和读取操作频繁的应用,但不适合在中间位置频繁插入或删除的情况。
📝 结语
ArrayList
的源码实现展现了 Java 集合框架的设计之美。从构造函数到核心方法,我们看到了一个基于数组的动态数据结构如何通过扩容、移位等操作,平衡了效率和易用性。在实际开发中,选择集合类型时可以根据具体场景的需求来判断 ArrayList
是否为最佳选择。希望通过这篇解析,你能更加得心应手地使用 ArrayList
,更深入地理解 Java 集合框架的实现原理!
… …
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
… …
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。