在 Java 中,并没有一个叫做 StringDynamicArray 的内置类,当开发者提到“字符串动态数组”时,通常指的是以下两种情况之一:

- 一个可以动态增长/缩小的、专门用来存储
String对象的集合类。 这是最常见的理解。 - 一个自己实现的、可变大小的数组数据结构,用于存放
String。 这通常用于学习数据结构的目的。
下面我将围绕这两种情况进行详细解释。
使用 Java 集合框架(最常用、最推荐)
在实际开发中,我们几乎总是使用 Java 集合框架中的类来处理动态数组的需求,对于存储 String 类型,最核心、最常用的类是 ArrayList<String>。
为什么选择 ArrayList<String>?
- 动态大小:
ArrayList内部使用一个数组来存储元素,当元素数量超过当前数组容量时,它会自动创建一个更大的新数组,并将所有旧元素复制到新数组中,这个过程对开发者是透明的,实现了“动态”增长。 - 类型安全:通过泛型
<String>,我们确保了这个列表中只能存放String对象,尝试添加其他类型(如Integer)会在编译时报错,避免了运行时的ClassCastException。 - 丰富的 API:
ArrayList提供了大量方便的方法,如add(),get(),set(),remove(),size()等,操作非常简单。
ArrayList<String> 的基本用法
下面是一个完整的示例,展示了如何创建、添加、访问、修改和删除 ArrayList 中的字符串。
import java.util.ArrayList;
public class StringArrayListExample {
public static void main(String[] args) {
// 1. 创建一个空的 String 类型的 ArrayList
ArrayList<String> fruits = new ArrayList<>();
// 2. 向列表中添加元素 (动态增长)
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
System.out.println("初始列表: " + fruits); // 输出: [Apple, Banana, Orange]
System.out.println("当前大小: " + fruits.size()); // 输出: 3
// 3. 在指定位置添加元素
fruits.add(1, "Mango");
System.out.println("在索引1处添加Mango后: " + fruits); // 输出: [Apple, Mango, Banana, Orange]
// 4. 访问元素
String firstFruit = fruits.get(0);
System.out.println("第一个水果是: " + firstFruit); // 输出: Apple
// 5. 修改元素
fruits.set(2, "Grape");
System.out.println("将索引2处的元素修改为Grape后: " + fruits); // 输出: [Apple, Mango, Grape, Orange]
// 6. 删除元素
fruits.remove("Apple"); // 删除第一个值为"Apple"的元素
System.out.println("删除'Apple'后: " + fruits); // 输出: [Mango, Grape, Orange]
fruits.remove(0); // 删除索引为0的元素
System.out.println("删除索引0的元素后: " + fruits); // 输出: [Grape, Orange]
// 7. 遍历列表
System.out.println("使用 for-each 遍历:");
for (String fruit : fruits) {
System.out.println(fruit);
}
// 8. 检查元素是否存在
boolean hasOrange = fruits.contains("Orange");
System.out.println("列表中是否包含'Orange'? " + hasOrange); // 输出: true
// 9. 清空列表
fruits.clear();
System.out.println("清空列表后: " + fruits); // 输出: []
System.out.println("清空后大小: " + fruits.size()); // 输出: 0
}
}
其他相关的集合类
除了 ArrayList,根据不同的需求,你还可以选择其他集合类:

| 集合类 | 特点 | 适用场景 |
|---|---|---|
ArrayList<String> |
基于动态数组,随机访问(get/set)速度快,增删中间元素慢。 | 最常用,当你需要频繁地通过索引访问元素,且不介意在中间增删元素时。 |
LinkedList<String> |
基于双向链表,增删元素(尤其是在头部或尾部)速度快,随机访问慢。 | 当你需要在列表的头部或频繁进行增删操作时。 |
HashSet<String> |
基于哈希表,元素无序且唯一,查找速度极快。 | 当你需要存储一组不重复的字符串,且不关心它们的顺序时。 |
TreeSet<String> |
基于红黑树,元素唯一且自动排序(按字典序)。 | 当你需要存储一组不重复的字符串,并且希望它们总是按特定顺序(如字母顺序)排列时。 |
对于“字符串动态数组”,ArrayList<String> 是你的首选。
自己实现一个动态数组(学习目的)
如果你正在学习数据结构,或者想了解其底层原理,可以尝试自己实现一个简单的动态数组,这个数组将使用一个固定大小的内部数组,并在空间不足时进行扩容。
核心思想
- 内部存储:使用一个
String[]数组作为底层存储。 - 容量与大小:
capacity表示内部数组的总长度,size表示当前存储的元素个数。 - 添加元素:
size < capacity,直接在size位置赋值,size++。size == capacity,说明数组已满,需要扩容:- 创建一个更大的新数组(通常是容量的 2 倍)。
- 将旧数组中的所有元素复制到新数组。
- 将新数组赋值给内部引用,并更新
capacity。 - 然后再添加新元素。
- 获取元素:直接通过索引访问内部数组。
简单的代码实现
这是一个非常基础的实现,只包含 add 和 get 方法。
public class MyStringDynamicArray {
private String[] array;
private int size; // 当前元素数量
private int capacity; // 数组总容量
// 构造函数,初始化容量
public MyStringDynamicArray(int initialCapacity) {
if (initialCapacity <= 0) {
throw new IllegalArgumentException("初始容量必须大于0");
}
this.array = new String[initialCapacity];
this.size = 0;
this.capacity = initialCapacity;
}
// 默认构造函数
public MyStringDynamicArray() {
this(10); // 默认初始容量为10
}
// 添加元素
public void add(String element) {
// 检查是否需要扩容
if (size == capacity) {
// 扩容为原来的2倍
resize(2 * capacity);
}
// 添加元素
array[size] = element;
size++;
}
// 获取元素
public String get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引 " + index + " 超出范围 (0-" + (size - 1) + ")");
}
return array[index];
}
// 获取当前元素数量
public int getSize() {
return size;
}
// 获取当前容量
public int getCapacity() {
return capacity;
}
// 扩容的核心方法
private void resize(int newCapacity) {
String[] newArray = new String[newCapacity];
// 将旧数组的内容复制到新数组
for (int i = 0; i < size; i++) {
newArray[i] = array[i];
}
// 更新内部数组和容量
this.array = newArray;
this.capacity = newCapacity;
System.out.println("数组已扩容,新容量: " + newCapacity);
}
// 打印数组内容
public void printArray() {
System.out.print("[");
for (int i = 0; i < size; i++) {
System.out.print(array[i]);
if (i < size - 1) {
System.out.print(", ");
}
}
System.out.println("]");
}
// 测试代码
public static void main(String[] args) {
MyStringDynamicArray myArray = new MyStringDynamicArray(3); // 初始容量为3
myArray.add("Java");
myArray.add("Python");
myArray.add("C++");
System.out.println("添加3个元素后:");
myArray.printArray(); // 输出: [Java, Python, C++]
System.out.println("大小: " + myArray.getSize() + ", 容量: " + myArray.getCapacity());
System.out.println("\n添加第4个元素 (将触发扩容):");
myArray.add("JavaScript");
myArray.printArray(); // 输出: [Java, Python, C++, JavaScript]
System.out.println("大小: " + myArray.getSize() + ", 容量: " + myArray.getCapacity());
System.out.println("\n获取索引为1的元素: " + myArray.get(1)); // 输出: Python
}
}
| 特性 | ArrayList<String> (推荐) |
自定义 MyStringDynamicArray |
|---|---|---|
| 来源 | Java 标准库 | 自己实现 |
| 易用性 | 非常高,API 丰富 | 需要自己编写所有方法 |
| 性能 | 经过高度优化,性能稳定 | 性能取决于实现,但原理相同 |
| 功能 | 功能强大(排序、查找、删除等) | 功能需要自己扩展 |
| 适用场景 | 所有日常和商业开发 | 学习数据结构和算法 |
在实际项目中,请毫不犹豫地使用 ArrayList<String>,它经过了数百万开发者测试,性能可靠,功能强大,能让你专注于业务逻辑而不是底层实现,自己动手实现一个动态数组,则是一个极好的编程练习,能让你深刻理解其工作原理。

