手写 ArrayList

1、MyList 接口

/**
 * 用于 MyArrayList 继承
 *
 * @param <E>
 */
public interface MyList<E> {

    /**
     * 添加一个元素
     *
     * @param element : 元素
     * @return : 返回是否插入成功 boolean
     */
    public boolean add(E element);

    /**
     * 指定位置添加元素
     *
     * @param index   : 要添加的元素位置
     * @param element : 元素
     */
    public void add(int index, E element);

    /**
     * 获取指定索引位置的元素
     *
     * @param index : 要获取的元素位置
     * @return : 返回获取的元素
     */
    public E get(int index);

    /**
     * 替换指定索引位置的元素
     *
     * @param index   : 要替换的元素位置
     * @param element : 要替换的元素
     * @return : 返回旧的元素
     */
    public E set(int index, E element);

    /**
     * 移除指定索引位置的元素
     *
     * @param index : 要移除的元素位置
     * @return : 返回被移除的元素
     */
    public E remove(int index);

    /**
     * 获取 MyArrayList 大小, 即 index + 1
     *
     * @return
     */
    public int size();

    /**
     * 清空数组
     */
    public void clear();

}

2、MyArrayList 实现类

public class MyArrayList<E> implements MyList<E> {

    /**
     * 0.0 ArrayList 底层采用数组存放
     */
    private E[] elementData;

    /**
     * 0.1 ArrayList 的大小(它包含的元素数),
     * 也可表示为下一个元素插入位置(即: index+1)
     */
    private int size;

    /**
     * 0.2 默认 Object[] 数组容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 0.3 初始化 默认初始化容量
     */
    public MyArrayList() {
        elementData = (E[]) new Object[DEFAULT_CAPACITY];
    }

    /**
     * 0.3 初始化 默认初始化容量
     *
     * @param initialCapacity : 容量大小 int 类型
     */
    public MyArrayList(int initialCapacity) {
        if (initialCapacity < 0) {
            // 抛出 非法参数异常
            throw new IllegalArgumentException();
        }
        // 初始化数组容量为 initialCapacity
        elementData = (E[]) new Object[initialCapacity];
    }

    /**
     * 1.0 判断 index 是否合法
     *
     * @param index : 要处理的索引值
     */
    private void rangCheck(int index) {
        // 判断 index 是否合法
        if (index < 0 || index >= size) {
            // 抛出 数组下标越界异常.
            throw new IndexOutOfBoundsException();
        }
    }

    /**
     * 1.0 判断 add() 方法的 index 是否合法
     *
     * @param index : 要处理的索引值
     */
    private void rangCheckForAdd(int index) {
        // 判断 index 是否合法
        if (index < 0 || index > size) {
            // 抛出 数组下标越界异常.
            throw new IndexOutOfBoundsException();
        }
    }

    /**
     * 2.0 确认容量进行扩容
     */
    private void ensureCapacity() {
        //① “下一个插入元素的索引值size” 比 数组长度小, 无需扩容
        if (size < elementData.length) {
            return;
        }

        //② 新的容量 = 旧容量 * 1.5
        int newCapacity = elementData.length + (elementData.length >> 1);// *1.5(扩容1.5倍)

        //③ 生成一个新的数组
        E[] newElements = (E[]) new Object[newCapacity];

        //④ 复制到新的数组
        for (int i = 0; i < size; i++) {
            newElements[i] = elementData[i];
        }

        //⑤ 将 elements 指向新的数组.
        elementData = newElements;
    }

    /**
     * 0.00 添加一个元素
     *
     * @param element : 元素
     * @return : 返回是否插入成功 boolean
     */
    @Override
    public boolean add(E element) {

        //2.01 扩容
        // 结合 “0.00 在某个位置添加某个元素” ,修改 1.01 代码
        add(size, element);

        //1.01 在元素数组elementData的 index = size 的位置插入该object元素
        // 并且在插入完成后 size++ , 即: 为元素数组保存一个空元素的索引elementData[size] = null .
        /* 代码1.01: */
        // elementData[size++] = object;

        return true;
    }

    /**
     * 0.00 在某个位置添加某个元素
     *
     * @param index   : 要添加的元素位置
     * @param element : 元素
     */
    @Override
    public void add(int index, E element) {
        //1.03 判断 index 是否合法
        rangCheckForAdd(index);

        //2.01 扩容
        ensureCapacity();

        //1.02 先将 elementData[index] 后的所有 object 向后移动一位, 将 elementData[index] 的位置空出来,
        // 再将 elementData[index] = object.
        // ①先将 i 的初始值赋为 size, 即: 当前 elementData 元素数组中 ”空(null)元素“ 索引值
        // ②再判断要插入的 index 位置是否比 i 小
        // ③如果满足②条件, 执行 elementData[i] = elementData[i-1]; 将元素后移一位
        // ④for循环: 直到 i = index+1 , 此时 elementData[index] 位置为 null.
        for (int i = size; i > index; i--) {
            elementData[i] = elementData[i - 1];
        }
        // ⑤将④处理后的 elementData[index] = object;
        elementData[index] = element;
        size++;// ⑥为下一个要添加的元素保留位置
    }

    /**
     * 0.00 查找某个位置的元素
     *
     * @param index : 要获取的元素位置
     * @return : 返回获取的元素
     */
    @Override
    public E get(int index) {
        //① 判断 index 是否合法
        rangCheck(index);
        //② 返回对应 index 位置对应的元素
        return elementData[index];
    }

    /**
     * 0.00 覆盖某个位置的元素
     *
     * @param index   : 要替换的元素位置
     * @param element : 要替换的元素
     * @return : 返回被覆盖的元素
     */
    @Override
    public E set(int index, E element) {
        //① 判断 index 是否合法
        rangCheck(index);

        //② 获取被覆盖的元素
        E oldValue = elementData[index];

        //③ 覆盖 index 位置的元素
        elementData[index] = element;

        //⑤ 返回被覆盖的元素
        return oldValue;
    }

    /**
     * 0.00 移除指定位置的元素
     *
     * @param index : 要移除的元素位置
     * @return : 返回要移除的元素
     */
    @Override
    public E remove(int index) {
        //① 判断 index 是否合法
        rangCheck(index);

        //② 获取要移除的元素
        E oldValue = elementData[index];

        //③ 将要移除的元素之后的元素向前移动一位
        for (int i = index; i < size; i++) {
            elementData[i] = elementData[i + 1];
        }

        //④ 下一个元素插入位置索引值减 1
        //size--;
        //⑤ ”下一个元素插入位置“ = null
        //elementData[size] = null;

        //⑥ 对 ④、⑤ 步进行简化
        elementData[--size] = null;

        //⑥ 返回要移除的元素
        return oldValue;
    }

    /**
     * 0.00 返回数组大小
     *
     * @return
     */
    @Override
    public int size() {
        return size;
    }

    /**
     * 0.00 清空数组
     */
    @Override
    public void clear() {

        //① 循环清空数组中所有元素
        for (int i = 0; i < size; i++) {
            elementData[i] = null;
        }

        //② 将数组大小置为 0
        size = 0;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer("Size = " + size + ", Data = ").append("[");
        for (int i = 0; i < size; i++) {
            sb.append(elementData[i] + ", ");
            if (i == size - 1) {
                sb.append(elementData[i]);
            }
        }
        sb.append("]");

        return sb.toString();
    }

}

3、Student 测试实体类

public class Student {

    private int id;

    private String name;

    private String address;

    public Student(int id, String name, String address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getAddress() {
        return address;
    }

    @Override
    protected void finalize() {
        System.out.println("This desctory!");
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", Address='" + address + '\'' +
                '}';
    }

}

4、测试类

public class Test {
    
    public static void main(String[] args) {

        MyArrayList arrayList = new MyArrayList();

        arrayList.add(new Student(1, "梨花1", "龙门大厦1"));
        arrayList.add(new Student(2, "梨花2", "龙门大厦2"));
        arrayList.add(new Student(3, "梨花3", "龙门大厦3"));
        arrayList.add(new Student(4, "梨花4", "龙门大厦4"));
        arrayList.add(new Student(1, "梨花1", "龙门大厦1"));
        arrayList.add(new Student(2, "梨花2", "龙门大厦2"));
        arrayList.add(new Student(3, "梨花3", "龙门大厦3"));
        arrayList.add(new Student(4, "梨花4", "龙门大厦4"));
        arrayList.add(new Student(1, "梨花1", "龙门大厦1"));
        arrayList.add(new Student(2, "梨花2", "龙门大厦2"));
        arrayList.add(new Student(3, "梨花3", "龙门大厦3"));
        arrayList.add(new Student(4, "梨花4", "龙门大厦4"));

        System.out.println("添加 " + arrayList);

        arrayList.add(4, new Student(8, "梨花8", "龙门大厦8"));

        System.out.println("插入 " + arrayList);

        System.out.println("添加一个元素 " + arrayList.add(new Student(10, "梨花4", "龙门大厦4")));
        System.out.println("添加一个元素 " + arrayList);

        System.out.println("获取元素" + arrayList.get(4));

        System.out.println("覆盖元素 " + arrayList.set(4, new Student(888, "梨花8", "龙门大厦8")));
        System.out.println("覆盖元素 " + arrayList);

        System.out.println("移除元素 " + arrayList.remove(4));
        System.out.println("移除元素 " + arrayList);

        System.out.println("元素数量 " + arrayList.size());

        arrayList.clear();
        System.out.println("清空数组 " + arrayList);

        // 告诉虚拟机进行垃圾回收
        System.gc();
        System.out.println(arrayList);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值