数组MyArraysList的代码实现

一、需要实现的API

public class MyArrayList<E> {
    private E[] data;                            //存放数据
    private int size;                            //元素个数
    private static final int INIT_CAP = 1;       //初始容量

    public MyArrayList();                        //无参构造函数
    
    public MyArrayList(int initCapacity);        //构造函数

    // *** 工具方法 ***
    public int size();                           //返回数组中元素个数
       
    public boolean isEmpty();                    //判断数组是否为空

    private void resize(int newCap);             //将数组的容量改为newCap

    private void checkElementIndex(int index);   //检查index索引位置是否可以存在元素
    private boolean isElementIndex(int index);   //函数checkElementIndex的辅助函数

    private void checkPositionIndex(int index);  //检查index索引位置是否可以插入元素
    private boolean isPositionIndex(int index);  //函数checkPositionIndex的辅助函数
    
    // *** 增 ***
    public void addLast(E e);                    //数组尾部添加元素e
    
    public void add(int index, E e);             //将元素e插入位置index
    
    public void addFirst(E e);                   //将元素e插入数组头部

    // *** 删 ***
    public E removeLast();                       //删除数组中最后一个元素

    public E remove(int index);                  //删除索引为index的元素

    public E removeFirst();                      //删除数组中第一个元素

    // *** 查 ***
    public E get(int index);                     //查找索引为index的元素
    
    // *** 改 ***
    public E set(int index, E element);          //将数组中索引为index的元素值改为element
}

二、构造函数的实现

public MyArrayList() {
    this(INIT_CAP);
}

public MyArrayList(int initCapacity) {
    data = (E[]) new Object[initCapacity];
    size = 0;
}

三、工具函数的实现

1. size()和isEmpty()的实现

public int size() {
    return size;
}

public boolean isEmpty() {
    return size == 0;
}

2. resize函数实现

private void resize(int newCap) {
    //如果newCap比元素个数还小,返回
    if (size > newCap) {
        return;
    }
    
    //开一个容量为newCap的数组temp
    E[] temp = (E[]) new Object[newCap];

    //将data[0..]搬移到temp[0..] 总共搬移元素size个
    System.arraycopy(data, 0, temp, 0, size);
    data = temp;
}

3. 索引检查函数实现

// 检查index索引位置是否可以存在元素
private void checkElementIndex(int index) {
    if (!isElementIndex(index)) {
        throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
    }
}
private boolean isElementIndex(int index) {
    return index >= 0 && index < size;
}

// 检查index索引位置是否可以添加元素
private void checkPositionIndex(int index) {
    if (!isPositionIndex(index)) {
        throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
    }
}
private boolean isPositionIndex(int index) {
    return index >= 0 && index <= size;
}

checkElementIndex与checkPositionIndex函数的区别

 checkElementIndex用于检查index索引位置是否可以存在元素

如上图,如果合法索引是0~3,如果给一个下标4,那么checkElementIndex会认为4不合法

而checkPositionIndex用于检查index索引位置是否可以添加元素

添加元素时,元素应该是“见缝插针”,所以下标4也是合法的。

四、数组增删查改的实现

1. 增

public void addLast(E e) {
    int cap = data.length;
    // 看data数组容量够不够
    if (size == cap) {
        resize(2 * cap);
    }
    // 在尾部插入元素
    data[size] = e;
    size++;
}

public void add(int index, E e) {
    // 检查索引越界
    checkPositionIndex(index);

    int cap = data.length;
    // 看data数组容量够不够
    if (size == cap) {
        resize(2 * cap);
    }

    // 搬移数据data[index...] -> data[index+1...]
    System.arraycopy(data, index, data, index+1, size - index);

    // 插入
    data[size] = e;
    size++;
}

public void addFirst(E e) {
    add(0, e);
}

2. 删

public E removeLast() {
    //如果数组为空,删除操作失败
    if (size == 0) {
        throw new NoSuchElementException();
    }

    int cap = data.length;
    // 可以缩容,节约空间
    if (size == cap / 4) {
        resize(cap / 2);
    }

    E deletedVal = data[size - 1];
    // 删除最后一个元素
    data[size - 1] = null;
    size--;

    return deletedVal;
}

public E remove(int index) {
    // 检查索引越界
    checkElementIndex(index);

    E deletedVal = data[index];
    // 搬移数据data[index+1...] -> data[index...]
    System.arraycopy(data, index+1, data, index, size-index-1);
    data[size - 1] = null;
    size--;

    return deletedVal;
}

public E removeFirst() {
    return remove(0);
}

3. 查

public E get(int index) {
    // 检查索引越界
    checkElementIndex(index);

    return data[index];
}

4. 改

public E set(int index, E element) {
    // 检查索引越界
    checkElementIndex(index);
    // 修改数据
    E oldVal = data[index];
    data[index] = element;
    return oldVal;
}

总结

数组几个API的实现较为简单,要注意的是带下标index增删查改时,需先检查一下index是否合法;除此之外,在增删操作中,对数组进行自动扩容和缩容可以提高空间的利用率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值