实现数组
1.首先定义一个数组的雏形,这个数据类具有基本的属性和方法,实现了基本的数组类后我们可以创建一个数组,但无法对其元素进行操作,接下来就实现操作数组元素的方法
public class Array<E> { private E[] data; private int size; // 构造函数,传入数组的容量capacity构造Array public Array(int capacity){ data = (E[])new Object[capacity]; size = 0; } // 无参数的构造函数,默认数组的容量capacity=10 public Array(){ this(10); } // 获取数组的容量 public int getCapacity(){ return data.length; } // 获取数组中的元素个数 public int getSize(){ return size; } // 返回数组是否为空 public boolean isEmpty(){ return size == 0; } }
2.实现一个添加元素的add方法,需要提供插入的位置index以及需要插入的元素,当在index处插入元素的时候,index后面包括index的元素都需要向后移一位
// 在index索引的位置插入一个新元素e public void add(int index, E e){ //当数组已满,抛出异常 if(size == data.length) throw new IllegalArgumentException("添加失败,数组已满!"); //当index参数不合法,抛出异常 if(index < 0 || index > size) throw new IllegalArgumentException("添加失败,index参数不合法!"); //把index和index后面的元素向后移,然后在index出插入目标元素e,最后size自增。 for(int i = size - 1; i >= index ; i --) data[i + 1] = data[i]; data[index] = e; size ++; }
通过复用这个add方法我们可以实现往数组头部插入元素和往数组尾部插入元素的方法
// 在数组头部添加一个新元素 public void addFirst(E e){ add(0, e); } // 在数组尾部添加一个新元素 public void addLast(E e){ add(size, e); }
3.获取元素与更新元素
// 获取index索引位置的元素 public E get(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("获取失败,index不合法."); return data[index]; } // 修改index索引位置的元素为e public void set(int index, E e){ if(index < 0 || index >= size) throw new IllegalArgumentException("设置失败,index不合法."); data[index] = e; }
4.查找元素与删除元素
// 查找数组中元素e所在的索引,如果不存在元素e,则返回-1 public int find(E e){ //循环整个数组,存在e则返回索引i for(int i = 0 ; i < size ; i ++){ if(data[i].equals(e)) return i; } return -1; }
删除元素与添加元素相反,添加元素index后面的向后移,而删除元素则index后面的向前移
// 从数组中删除index位置的元素, 返回删除的元素 public E remove(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("删除失败,index不合法."); //index后面的元素都向前移一位,最后返回被删除的元素 E ret = data[index]; for(int i = index + 1 ; i < size ; i ++) data[i - 1] = data[i]; size --;
data[size] = null; return ret; }
通过复用remove方法,我们可以实现删除数组头部元素和尾部元素的方法
// 从数组中删除第一个元素, 返回删除的元素 public E removeFirst(){ return remove(0); } // 从数组中删除最后一个元素, 返回删除的元素 public E removeLast(){ return remove(size - 1); }
有时我们并不是用index删除元素,而是希望根据元素本身的值进行删除,我们可以通过复用find方法实现这个操作
// 从数组中删除元素e public void removeElement(E e){ int index = find(e); if(index != -1) remove(index); }
5.数组的扩缩容
当数组已满就不能再添加元素显然是不合理的,所以我们需要实现数组的扩缩容,也就是动态数组。首先我们先实现resize方法,注意这个方式是私有的,毕竟不能让使用者随意resize。
// 将数组空间的容量变成newCapacity大小 private void resize(int newCapacity){ //新建一个data数组,根据传入的参数设定数组大小,然后把原data数组的元素复制过去,最后data指向新数组。 E[] newData = (E[])new Object[newCapacity]; for(int i = 0 ; i < size ; i ++) newData[i] = data[i]; data = newData; }
实现好resize方法后我们就可以对add方法和remove方法进行修改
add方法,数组已满时不抛出异常,而是扩容
if(size == data.length) //扩容成原数组的2倍大小 resize(2 * data.length);
remove方法,数组过小时,缩容。
//元素的数量等于数组长度的四分之一时,把数组长度缩成原来的二分之一 if(size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);