封装一个ArrayBox--实际是ArrayList的底层简单实现
package arrayBox; /** * 设计一个类,可以新增,删除,获取元素 * * @author my 数组存储数据 ArrayBox存储 int[] arr=new int[10] ArrayBox box=new Array() * arr[0]=5 box.add(5); * 分析:作为用户而言,arraybox的好处是,1.不需关心索引,自动管理存在哪个位置,0号位置,或者1号位置 * 。2.不需要关心长度,不用担心存不下 * */ public class ArrayBox<E>{//泛型 private Object[] elementData;// 在box内部还是使用数组进行存储 private int size = 0;// 记录有效元素个数 private static final int DEFAULT_CAPACITY=10;//默认长度 public ArrayBox(){ elementData=new Object[DEFAULT_CAPACITY]; } //这两个构造方法的作用是让用户可以自己使用默认的长度,或者自定义 public ArrayBox(int capacity){ elementData=new Object[capacity]; } /** * 添加元素 * * @param element */ public boolean add(E element) { // 添加元素之前,首先得确保可以存的下 this.ensureCapacity(size+1);// 这里采用的是一个一个加的,所以需要的最小长度就是,原有效个数基础上加一个 // 如果上面这句代码执行没问题,要么空间够,不需要扩容,直接在旧数组中插入一个元素,要么不够,进行扩容复制到新数组后,指向旧数组,再插入 elementData[size++] = element;// 第一次是0号位置存储,并自增记录有效个数 return true;// 返回true表示存储成功 } /** * 获取元素 * @param index * @return */ public Object get(int index){ //先检查index是否合法 >=0 <=size this.rangeCheck(index); return elementData[index]; } /** * 删除元素 * 需要删除的那个元素索引 * return 删除的那个元素 */ public Object remove(int index) { this.rangeCheck(index); //先將index位置的旧值保存起来、 Object oldValue=elementData[index]; //删除的方法是遍历后一个元素覆盖前一个元素 //10.20.30.40.50.60.0000 //10 20 40 40 50 60 0000 //10 20 40 50 50 60 0000 //10 20 40 50 60 60 0000 //10 20 40 50 60 0 0000 /*这种写法会导致一个问题,就是如果有效元素个数刚刚填满数组,那么遍历最后一次将最后一个元素用有效元素之外的0覆盖时数组越界 for(int i=index;i<size;i++){ elementData[i]=elementData[i+1]; } */ for(int i=index;i<size-1;i++){ elementData[i]=elementData[i+1]; } elementData[--size]=0;//避免了上诉写法的数组越界,记录有效元素-1,并将最后一个元素,这里是60,替换为0 return oldValue;//返回删除的元素给用户 } private void rangeCheck(int index){ if(index<0 || index>=size){ throw new BoxIndexOutOfBoundsException();//new一个自定义的异常对象,把它抛出来 } } /** * 确保容量够用,目前我们声明的数组是10个长度,那么得比较存入的长度是否超过10 * * @return */ private void ensureCapacity(int minCapacity) { if (minCapacity - elementData.length > 0) { // 需要的最小长度比原数组长度还大,需要扩容 this.grow(minCapacity); } } /** * 扩容 * @param minCapacity */ private void grow(int minCapacity) { int oldCapacity = elementData.length;// 原数组长度 int newCapacity = oldCapacity + oldCapacity >> 1;// 这里扩容1.5倍。乘法不是乘以2的倍数,底层效率,位运算更高 if (newCapacity - minCapacity < 0) {// 新计算得到的长度仍然比需要的最小长度小,那么直接赋值需要的最小长度作为新新数组长度 newCapacity = minCapacity; } // 按照上面的计算得到一个newCapacity,创建一个新数组,将旧数组的东西全部复制到新数组,把旧数组的名字给新数组用 this.elementData = this.copyOf(elementData, newCapacity); } /** * 创建一个新数组,将旧数组的值复制到新数组 * @param oldArray * @param newCapacity * @return array */ private Object[] copyOf(Object[] oldArray, int newCapacity) { Object[] newArray = new Object[newCapacity]; for (int i = 0; i < oldArray.length; i++) { newArray[i] = oldArray[i]; } return newArray; } } package arrayBox; public class Test { public static void main(String[] args) { ArrayBox box =new ArrayBox(); box.add(10); } } package arrayBox; /** * 自定义异常类 * @author my * */ public class BoxIndexOutOfBoundsException extends RuntimeException{ public BoxIndexOutOfBoundsException(){ } public BoxIndexOutOfBoundsException(String msg){ super(msg);//调用父类的带参构造方法 } }