Java ArrayList 底层方法自我实现
Java ArrayList 基于动态数组实现 List 接口,本文通过手写代码演示其核心方法。涵盖初始化、扩容机制(grow)、元素增删改查(add, remove, get, set)及遍历查找(contains, indexOf)。重点解析数组满时如何复制扩容、插入删除时的数据移动逻辑,帮助深入理解顺序表底层原理。

Java ArrayList 基于动态数组实现 List 接口,本文通过手写代码演示其核心方法。涵盖初始化、扩容机制(grow)、元素增删改查(add, remove, get, set)及遍历查找(contains, indexOf)。重点解析数组满时如何复制扩容、插入删除时的数据移动逻辑,帮助深入理解顺序表底层原理。

【前言】
ArrayList是 Java 集合框架中 List 接口的动态数组实现,可以方便的存储和操作数据。它提供了一系列方法,便于我们进行增删查改,这篇文章是进行 ArrayList 的一个自我实现,让我们从底层更深度地理解 ArrayList(顺序表)
arr: 创建一个整型数组,用来存储数据;usedSize: 有效数据,也就是真实的元素个数;
DEFAULT_CAPACITY:默认数组容量
MyArrayList():构造方法,初始化数组长度为默认的容量
public class MyArrayList implements IList {
private int[] arr; // 存储数据
private int usedSize; // 有效数据个数
public static final int DEFAULT_CAPACITY = 10; // 默认数组容量
public MyArrayList() {
this.arr = new int[DEFAULT_CAPACITY];
}
}
ArrayList 的常见方法如下:

public void add(int data) {
// 判断顺序表是否满了
if (isFull()) {
// 扩容 grow();
grow();
}
// 存储
this.arr[this.usedSize] = data;
this.usedSize++;
}
public boolean isFull() {
return this.usedSize == this.arr.length;
}
public void grow() {
this.arr = Arrays.copyOf(this.arr, 2 * this.arr.length);
}
添加元素时,要先检查数组是否已满(
isFull()通过比较数组的长度和元素个数),如果满了,就要进行扩容grow(),这里是 copy 两倍的数组容量,然后再进行存储
public void add(int pos, int data) {
// 检查是不是满的
if (isFull()) {
grow();
}
checkPos(pos, "add 方法执行的时候 pos 位置不合法");
// 判断是不是放在 usedSize 位置
if (pos == usedSize) {
arr[pos] = data;
usedSize++;
return;
}
// 如果放在前面,就要移动数据
for (int i = usedSize - 1; i >= pos; i--) {
arr[i + 1] = arr[i];
}
arr[pos] = data;
usedSize++;
}
private void checkPos(int pos, String msg) {
if (pos < 0 || pos > usedSize) {
throw new PosIllegalityException(msg);
}
}

还是先要检查容量是否已满
isFull(),满了就要进行扩容grow(),然后添加时,要先检查 pos 位置是否合法,如上图,pos < 0 || pos > usedSize 就是不合法的,在这个范围则会抛出我们自定义的PosIllegalityException异常,正常情况下进行添加:将 pos 位置及后面的元素统统向后移动一个位置,为要添加的元素腾出位置,然后有效数据 usedSize++
public boolean contains(int toFind) {
for (int i = 0; i < this.usedSize; i++) {
if (arr[i] == toFind) {
return true;
}
}
return false;
}
使用 for 循环遍历整个数组,if 语句判断当前元素是否是你要找的元素 toFind,是返回 true,不是返回 false
public int indexOf(int toFind) {
for (int i = 0; i < this.usedSize; i++) {
if (arr[i] == toFind) {
return i;
}
}
return -1;
}
同理:使用 for 循环遍历整个数组,if 语句判断当前元素是否是你要找的元素 toFind,是返回对应元素的下标 i,不是返回 -1
public int get(int pos) {
if (isEmpty()) {
throw new EmptyListException("当前顺序表为空");
}
checkPos(pos, "get 方法的 pos 位置不合法");
return arr[pos];
}
private void checkPos(int pos, String msg) {
if (pos < 0 || pos >= usedSize) {
throw new PosIllegalityException(msg);
}
}
public boolean isEmpty() {
return usedSize == 0;
}
获取元素,先检查 pos 位置是否为空
isEmpty(),如果为空,抛出我们的自定义异常EmptyListException,然后检查 pos 位置是否合法 pos<0 || pos >= usedSize 这个范围就是不合法的,抛出我们的自定义异常PosIllegalityException,最后就可以返回 pos 位置的元素
public void set(int pos, int value) {
if (isEmpty()) {
throw new EmptyListException("当前顺序表为空");
}
checkPos(pos, "set 方法执行的时候 pos 位置不合法" + pos);
arr[pos] = value;
}
替换时要先检查是否为空
isEmpty(),为空抛出自定义异常EmptyListException,不为空检查 pos 位置是否合法,最后将给定的值替换指定的数组元素
public void remove(int toRemove) {
if (isEmpty()) {
throw new EmptyListException("当前顺序表为空");
}
// 查找要删除数据的下标
int index = indexOf(toRemove);
if (index == -1) {
System.out.println("没有你要删除的数据");
return;
}
for (int i = index; i < usedSize - 1; i++) {
arr[i] = arr[i + 1];
}
usedSize--;
// arr[usedSize] = null;如果是引用类型,需要手动置空
}

还是先检查是否为空,然后可以通过
indexOf(toRemove)查找要删除的元素,如果 index == -1,则没有你要删除的元素,如果有,进行覆盖删除,让后面的元素逐一向前移动一个位置直到你要,直到覆盖掉你要删除的元素,最后将有效元素 usedSize–
public int size() {
return this.usedSize;
}
public void clear() {
for (int i = 0; i < this.usedSize; i++) {
arr[i] = 0;
}
usedSize = 0;
}
这篇文章只是从深度的实现了一下 ArrayList 提供的一系列方法,以便于更好地去理解和使用 ArrayList,让我们认识到了,数据结构的学习和使用,要考虑到所有方面,对我们的逻辑思维能力要求很高,同样也会提高我们这方面的能力,相关的其他内容后面会详细道来

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online