一、线性表(ArrayList)
1、在学习ArrayList之前,先了解一下线性表的概念。
线性表(Linear List)是一种逻辑结构,其核心特征是:数据之间是一对一的顺序关系,除了第一个元素,每个元素有且只有一个前驱(在这个元素前面的那个元素);除了最后一个元素,每个元素有且只有一个后继(在这元素后面的那个元素)。通俗的说:线性表就是 一条“线”式的序列。
下面举一个线性表例子:
| A | B | C | D | 元素 |
| 0 | 1 | 2 | 3 | 下标 |
前驱/后继关系: NULL A
B
C
D
NULL A的前驱是NULL,后继是B;B的前驱是A,后是C;C前驱是B,后继是D;D的前驱是C,后继是NULL;
2、ArrayList
线性表是一种逻辑结构,只是定义了“线”式排序的规则,并不在意元素是用数组实现还是用链表实现。在Java里面,这个抽象定义是通过List接口来实现的,List接口规定了线性表抽象定义的add,get,remove等等方法的具体操作。而我们要学习的ArrayList就是List接口实现的一种方式,是List的具体实现类。
ArrayList 是顺序存储的线性表,底层用动态数组。支持动态扩容,支持随机访问,允许重复和null。通俗的解释就是:ArrayList就像一个储物柜,每个格子都有编号(0、1、2....);可以很快的找到想要的格子(随机访问快);但是如果要在已有东西(元素)的格子中间插入新元素,就需要把后面的格子的元素都往后搬(插入删除慢);如果格子都满了,就换到一个更大的储物柜,把所有的格子都搬过去“System.arraycopy”(可扩容)。
底层数组结构:Object[] elementData elementData是存放数据的数组,就是这个储物柜。“capacity=8”说明这个储物柜里只有8个格子(元素);“size=5”说明目前已经放了5个元素。
capacity=8
elementData =[ A ][ B ][ C ][ D ][ E ][ ][ ][ ]
size=5
好了,基本的概念我们已经了解的差不多了,举一个代码示例来具体学习一下吧!
首先是引入ArrayList和Field(java.lang.reflect包里的类,用于获取类的成员变量),定义一个叫做ArrayListDemo的类和getCapacity方法 ,用来获取 ArrayList的底层数组长度(capacity)。
import java.util.ArrayList;
import java.lang.reflect.Field;
public class ArrayListDemo {
private static int getCapacity(ArrayList<?> list) {
try {
Field field = ArrayList.class.getDeclaredField("elementData");//反射找到 ArrayList 里名叫 elementData 的字段
field.setAccessible(true);//绕过 Java 的访问修饰符检查
Object[] elementData = (Object[]) field.get(list);//获取list 的 elementData 数组
return elementData.length;//返回底层数组capacity的长度
} catch (Exception e) {
e.printStackTrace();
return -1;
}//异常处理
}
public static void main(String[] args) {
// 初始化一个ArrayList
ArrayList<String> list = new ArrayList<>(8); // 初始容量 8
// 添加元素
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
// 打印当前状态
System.out.println("初始 ArrayList: " + list);
System.out.println("size = " + list.size());
System.out.println("capacity = " + getCapacity(list));
}
}
运行结果:
接着在 // 打印当前状态 下继续输入:
// 插入元素
list.add(2, "X"); // 在下标2的位置插入
System.out.println("\n插入 X 后: " + list);
System.out.println("size = " + list.size());
System.out.println("capacity = " + getCapacity(list));
// 删除元素
list.remove("C"); // 删除元素 "C"
System.out.println("\n删除 C 后: " + list);
System.out.println("size = " + list.size());
System.out.println("capacity = " + getCapacity(list));
// 修改元素
list.set(1, "Y");
System.out.println("\n修改下标1为Y后: " + list);
System.out.println("size = " + list.size());
System.out.println("capacity = " + getCapacity(list));
// 添加到超过容量,触发扩容
list.add("F");
list.add("G");
list.add("H");
list.add("I"); // 这一步超过初始容量8,会扩容
System.out.println("\n扩容后: " + list);
System.out.println("size = " + list.size());
System.out.println("capacity = " + getCapacity(list));
运行结果:
今天的学习就到这里,有什么不足还请指正。明天继续学习线性表中的另一种实现类LinkedList,并学习区分什么时候使用ArrayList,什么时候用LinkedList。