使用 Java 实现 ArrayList

2 min read

ArrayList 基本介绍

ArrayList 是 List 接口中最为常用的一个实现类,从名字可以看出,它与数组有着千丝万缕的关系。实际上,ArrayList 就是在底层维护了一个数组,这个数组不过是动态的、可以随时自动扩容的。往简单了说,ArrayList 就是一个动态数组。理解了这个,也就理解了 ArrayList 的精髓。今天看了源码,然后跟着简单地敲了一下,实现了里面的几个方法,在下面记录一下。

ArrayList 的实现

把 ArrayList 想象成一个数组,像 add、remove、get 以及 set 等常用方法闭着眼睛就能敲了,就不赘述代码的步骤了。下面直接上一车,哈哈哈😄

package com.realchoi.arraylist;

/**
 * 手动实现 ArrayList
 *
 * @author realchoi
 */
public class MyArrayList {
    // List 中元素的个数
    private int size;

    // List 中维护的数组(关键就在这)
    private Object[] elementData;

    /**
     * 无参构造方法,初始化 MyArrayList
     */
    public MyArrayList() {
        this(10);
    }

    /**
     * 有参构造方法,初始化 MyArrayList,并给定初始容量
     *
     * @param capacity 初始容量
     */
    public MyArrayList(int capacity) {
        if (capacity < 0) {
            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        elementData = new Object[capacity];
    }

    /**
     * 获取 List 中元素的个数
     *
     * @return
     */
    public int size() {
        return size;
    }

    /**
     * 将元素添加到 List 末尾
     *
     * @param element 待添加的元素
     */
    public void add(Object element) {
        // 添加时首先需要判断数组容量是否够用,否则进行扩容
        ensureCapacity();
        elementData[size] = element;
        size++;
    }


    /**
     * 在 List 的指定位置添加元素
     *
     * @param index   添加元素的位置
     * @param element 待添加的元素
     */
    public void add(int index, Object element) {
        // 先判断指定的位置是否越界
        rangeCheck(index);
        // 再扩容
        ensureCapacity();
        // index 位置的数组向后移动一位
        System.arraycopy(elementData, index, elementData, index + 1, size - index);
        elementData[index] = element;
        size++;
    }

    /**
     * 获取 List 指定位置的元素
     *
     * @param index 指定的位置
     * @return
     */
    public Object get(int index) {
        rangeCheck(index);
        return elementData[index];
    }

    /**
     * 移除指定位置的元素
     *
     * @param index 指定的位置
     * @return 移除的元素
     */
    public Object remove(int index) {
        rangeCheck(index);
        Object removedEle = elementData[index];
        elementData[index] = null;
        // index + 1 位置的数组往前移动一位
        System.arraycopy(elementData, index + 1, elementData, index, size - index - 1);
        size--;
        return removedEle;
    }

    /**
     * 删除指定的元素
     *
     * @param element 待删除的元素
     * @return 删除的元素的原位置
     */
    public int remove(Object element) {
        for (int i = 0; i < size; i++) {
            if (elementData[i].equals(element)) {
                // 删除第一个和待删除元素 equals 的元素
                elementData[i] = null;
                System.arraycopy(elementData, i + 1, elementData, i, size - i - 1);
                size--;
                return i;
            }
        }
        return -1;
    }

    /**
     * 设置指定位置的元素
     *
     * @param index   指定的位置
     * @param element 指定的元素
     * @return 原位置的元素
     */
    public Object set(int index, Object element) {
        rangeCheck(index);
        Object oldEle = elementData[index];
        elementData[index] = element;
        return oldEle;
    }

    /**
     * 判断 List 是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 查询 List 中第一个和指定元素匹配的元素的索引
     *
     * @param element 指定的元素
     * @return 元素的索引
     */
    public int indexOf(Object element) {
        // 先判断指定元素为 null 的情况
        if (element == null) {
            for (int i = 0; i < size; i++) {
                if (elementData[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = 0; i < size; i++) {
                if (elementData[i].equals(element)) {
                    return i;
                }
            }
        }
        // 不存在则返回 -1
        return -1;
    }

    /**
     * 查询 List 中最后一个和指定元素匹配的元素的索引
     *
     * @param element 指定的元素
     * @return 元素的索引
     */
    public int lastIndexOf(Object element) {
        if (element == null) {
            for (int i = size - 1; i >= 0; i--) {
                if (element == null) {
                    return i;
                }
            }
        } else {
            for (int i = size - 1; i >= 0; i--) {
                if (elementData[i].equals(element)) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 清空 List 中的元素
     */
    public void clear() {
        for (int i = 0; i < size; i++) {
            elementData[i] = null;
        }
        size = 0;
    }

    /**
     * 将 List 转为数组
     *
     * @return
     */
    public Object[] toArray() {
        Object[] array = new Object[size];
        for (int i = 0; i < size; i++) {
            array[i] = elementData[i];
        }
        return array;
    }

    /**
     * 将指定的 List 全部添加到原 List 的末尾
     *
     * @param myArrayList 待添加的 List
     */
    public void addAll(MyArrayList myArrayList) {
        // 扩容
        if (size + myArrayList.size == elementData.length) {
            Object[] newElementData = new Object[(size + myArrayList.size) * 2 + 1];
            System.arraycopy(elementData, 0, newElementData, 0, size);
            elementData = newElementData;
        }
        // 将待添加的 List 转为数组,并复制到原 List 的末尾
        Object[] newArray = myArrayList.toArray();
        System.arraycopy(newArray, 0, elementData, size, newArray.length);
        size = size + newArray.length;
    }

    /**
     * 将指定的 List 添加到原 List 的指定位置
     *
     * @param index       指定的位置
     * @param myArrayList 待添加的 List
     */
    public void addAll(int index, MyArrayList myArrayList) {
        rangeCheck(index);
        // 扩容
        if (size + myArrayList.size == elementData.length) {
            Object[] newElementData = new Object[(size + myArrayList.size) * 2 + 1];
            System.arraycopy(elementData, 0, newElementData, 0, size);
            elementData = newElementData;
        }
        // 原数组从 index 处向后移动,腾出位置插入新元素
        System.arraycopy(elementData, index, elementData, index + myArrayList.size, size - index);
        // 将待添加的 List 转为数组,并复制到原 List 的 index 处
        Object[] newArray = myArrayList.toArray();
        System.arraycopy(newArray, 0, elementData, index, newArray.length);
        size = size + newArray.length;
    }

    /**
     * 对 List 进行扩容
     */
    private void ensureCapacity() {
        if (size == elementData.length) {
            Object[] newElementData = new Object[elementData.length * 2 + 1];
            System.arraycopy(elementData, 0, newElementData, 0, size);
            elementData = newElementData;
        }
    }

    /**
     * 检查指定的位置是否越界
     *
     * @param index 指定的位置
     */
    private void rangeCheck(int index) {
        if (index < 0 || index >= size) throw new IndexOutOfBoundsException();
    }
}

以上只是简单实现了其中的几个方法,当做学习,不足以表现出 Java 中 ArrayList 类的特性,想理解更多,还需深入学习。

Over~😎