ArrayList.remove()的一个小细节

本文探讨了在使用ArrayList进行元素操作时遇到的自动装箱陷阱,详细解释了为何直接传入int值会导致IndexOutOfBoundsException,并提供了正确的解决方法。

不废话,先上代码:

 

ArrayList<Integer> col = new ArrayList<Integer>();
System.out.println("Initial size: " + col.size());
for(int i = 0; i < 20; i++)
    col.add(i + 10);

 

显然,上面这段代码再简单不过了,建立一个Interger类型参数的ArrayList.

于是考虑到要从ArrayList删除两个元素,比如10, 25。初步设想的代码如下:

 

col.remove(10);
col.remove(25);

 

   基于这种设想的原因是,既然ArrayList<Integer>里的类型是Integer,我传入一个int的应该可以自动实现autoboxing.那么,如果和设想的一样,col中的10和25两个元素都被删除了。

实际运行的结果不然:

 

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 25, Size: 20

at java.util.ArrayList.rangeCheck(ArrayList.java:604)

at java.util.ArrayList.remove(ArrayList.java:445)

at CollectionBasics.main(CollectionBasics.java:54)

从错误中间可以看到,提示的是访问数组索引越界了。怎么会这样呢?很显然,传入的10,25被当成索引而不是要移除的元素。
察看java doc里面才发现,里面有两个remove方法,分别定义如下:
public E remove(int index);

public boolean remove(Object o);
 
当我们传入int类型的时候,会自动被当成上面那个方法来调用。而下面那个移除某个特定元素的方法是需要传入一个Object对象。所以,为了移除制定的元素而不至于引起混淆的话,可以将传入的int先封装一下:
col.remove((Integer)10);
col.remove((Integer)25);
    这样结果就对了。

 

### 实现 ArrayList 并支持扩容/缩容功能 #### 概述 `ArrayList` 是一种基于连续内存区域的数据结构,类似于 C++ 中的 `std::vector` 或 Java 的 `ArrayList`。它的特点是能够动态调整大小以适应元素的变化需求。下面将详细介绍如何用 C 语言实现这一数据结构,并提供其核心功能。 --- ### **1. 功能设计** 我们需要实现以下内容: - **核心功能**:添加、删除、查找等基本操作。 - **动态调整容量**:通过 `resize()` 函数,在需要时自动扩增或缩减数组容量。 - **测试用例**:验证所有 API 是否正常工作。 以下是具体的文件划分: 1. **头文件 (`ArrayList.h`)** - 定义 `ArrayList` 数据结构及其相关接口函数原型。 2. **源文件 (`ArrayList.c`)** - 包含 `ArrayList` 的实现细节,包括初始化、插入、删除以及动态调整容量等功能。 3. **主程序文件 (`main.c`)** - 编写测试用例,对上述功能逐一验证。 --- ### **2. 文件实现** #### (1) ArrayList.h ```c #ifndef ARRAYLIST_H #define ARRAYLIST_H #include <stdbool.h> // 定义ArrayList结构体 typedef struct { int *data; // 存储数据的指针 size_t capacity;// 数组当前容量 size_t size; // 当前存储的有效元素个数 } ArrayList; // 初始化ArrayList void ArrayList_init(ArrayList *list); // 销毁ArrayList并释放资源 void ArrayList_destroy(ArrayList *list); // 添加元素到ArrayList末尾 bool ArrayList_add(ArrayList *list, int value); // 删除指定位置的元素 bool ArrayList_removeAt(ArrayList *list, size_t index); // 获取指定索引处的值 int ArrayList_get(ArrayList *list, size_t index); // 设置指定索引处的值 bool ArrayList_set(ArrayList *list, size_t index, int value); // 返回ArrayList中有效元素的数量 size_t ArrayList_size(ArrayList *list); // 调整ArrayList的容量(扩容/缩容) bool ArrayList_resize(ArrayList *list, size_t newCapacity); #endif /* ARRAYLIST_H */ ``` --- #### (2) ArrayList.c ```c #include "ArrayList.h" #include <stdlib.h> #include <stdio.h> // 初始默认容量 #define DEFAULT_CAPACITY 4 // 扩展系数(当容量不足时增加多少倍) #define RESIZE_FACTOR 2 // 改变ArrayList的容量 static bool resize(ArrayList *list, size_t newCapacity) { if (newCapacity == list->capacity || newCapacity == 0) return false; int *newData = realloc(list->data, sizeof(int) * newCapacity); if (!newData) return false; // 内存分配失败 list->data = newData; list->capacity = newCapacity; return true; } // 初始化ArrayList void ArrayList_init(ArrayList *list) { list->data = malloc(sizeof(int) * DEFAULT_CAPACITY); list->capacity = DEFAULT_CAPACITY; list->size = 0; } // 销毁ArrayList并释放资源 void ArrayList_destroy(ArrayList *list) { free(list->data); list->data = NULL; list->capacity = list->size = 0; } // 添加元素到ArrayList末尾 bool ArrayList_add(ArrayList *list, int value) { if (list->size >= list->capacity) { // 如果空间不够,则先扩充容量 if (!ArrayList_resize(list, list->capacity * RESIZE_FACTOR)) return false; } list->data[list->size++] = value; return true; } // 删除指定位置的元素 bool ArrayList_removeAt(ArrayList *list, size_t index) { if (index >= list->size || list->size == 0) return false; for (size_t i = index; i < list->size - 1; ++i) { list->data[i] = list->data[i + 1]; } --list->size; // 若剩余元素较少则缩小容量 if (list->size <= list->capacity / RESIZE_FACTOR && list->capacity > DEFAULT_CAPACITY) { ArrayList_resize(list, list->capacity / RESIZE_FACTOR); } return true; } // 获取指定索引处的值 int ArrayList_get(ArrayList *list, size_t index) { if (index >= list->size) return -1; // 索引越界返回错误码(-1) return list->data[index]; } // 设置指定索引处的值 bool ArrayList_set(ArrayList *list, size_t index, int value) { if (index >= list->size) return false; list->data[index] = value; return true; } // 返回ArrayList中有效元素的数量 size_t ArrayList_size(ArrayList *list) { return list->size; } // 公开调整容量的功能 bool ArrayList_resize(ArrayList *list, size_t newCapacity) { return resize(list, newCapacity); } ``` --- #### (3) main.c ```c #include "ArrayList.h" int main(void) { ArrayList list; ArrayList_init(&list); // 初始化ArrayList printf("初始状态:\n"); printf("Size=%zu, Capacity=%zu\n", ArrayList_size(&list), list.capacity); // 测试添加元素 for (int i = 0; i < 10; ++i) { ArrayList_add(&list, i * 10); } printf("\n添加10个元素后的状态(每步*10):\n"); for (size_t i = 0; i < ArrayList_size(&list); ++i) { printf("%d ", ArrayList_get(&list, i)); } printf("\nSize=%zu, Capacity=%zu\n", ArrayList_size(&list), list.capacity); // 测试获取和设置特定索引的值 printf("\n修改第5位的值为888:"); ArrayList_set(&list, 5, 888); for (size_t i = 0; i < ArrayList_size(&list); ++i) { printf("%d ", ArrayList_get(&list, i)); } // 测试删除中间元素 printf("\n删除第6位元素:"); ArrayList_removeAt(&list, 6); for (size_t i = 0; i < ArrayList_size(&list); ++i) { printf("%d ", ArrayList_get(&list, i)); } // 清理资源 ArrayList_destroy(&list); printf("\n清理完成.\n"); return 0; } ``` --- ### **运行结果示例** 假设我们按照上面代码执行,可能会得到类似的结果: ``` 初始状态: Size=0, Capacity=4 添加10个元素后的状态(每步*10): 0 10 20 30 40 50 60 70 80 90 Size=10, Capacity=16 修改第5位的值为888: 0 10 20 30 40 888 60 70 80 90 删除第6位元素: 0 10 20 30 40 888 70 80 90 清理完成. ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值