T9移动架构师成长路线学习第一天(必备数据结构_ArrayList)

50 阅读3分钟

 一、线性表(ArrayList)

1、在学习ArrayList之前,先了解一下线性表的概念。

线性表(Linear List)是一种逻辑结构,其核心特征是:数据之间是一对一的顺序关系,除了第一个元素,每个元素有且只有一个前驱(在这个元素前面的那个元素);除了最后一个元素,每个元素有且只有一个后继(在这元素后面的那个元素)。通俗的说:线性表就是 一条“线”式的序列。

下面举一个线性表例子:

ABCD元素
0123下标

前驱/后继关系:                NULL\leftarrow   A   \leftrightharpoons  B  \leftrightharpoons  C  \leftrightharpoons  D  \rightarrow 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。