用ArrayBox封装一个新的动态数组工具类,长度可变,仍然能实现存数据,删除数据,获取指定位置的数据,得到ArrayBox的有效长度的功能
用ArrayBox封装一个新的动态数组工具类,长度可变,仍然能实现存数据,删除数据,获取指定位置的数据,得到ArrayBox的有效长度的功能
数组:长度固定,在存数据和删除数据的时候,数组的长度不会发生变化,如果数组满了就无法进行存储,如果创建一个很大的数组,但是只存储了很少的数据又会造成内存浪费.所以我们练习修饰符(public.private)和类之间的关系来用ArrayBox封装一个具有数组存.取.删除求长度功能的新工具类.
package Util;
//用ArrayBox封装数组,用来实现动态数组(小List),用int类型来举例
public class ArrayBox implements Box {
private static final int DEFAULT_CAPACITY = 10;
//设计一个属性存储自己的属性,用来存放真实数据的 [ ]类型
private int[] elementDate;
//设计一个自己的属性,用来记录数组内有效的元素个数
private int size;//默认为0
//找一个小A同学,来确定容量是否够用
public ArrayBox() {
elementDate = new int [DEFAULT_CAPACITY];//如果不告知要创建的长度就创建一个长度为10的数组,这里写为静态常量而不直接用数字表示是为了增加其可读性
}
public ArrayBox(int capacity) {
elementDate = new int [capacity];
}
private void ensureCapacitvInternal(int minCapacitv) {
//判断 你需要的最小的容量比原数组的长度还要大
if(minCapacitv-elementDate.length >0 ) {
//需要扩容,找别人计算需要扩容的大小
this.grow(minCapacitv);
}
}
//小B同学 负责计算扩容的大小
private void grow(int minCapacitv) {
//需要计算扩容的大小 需要获取到之前数组的原始大小
int oldCapacitv = elementDate.length;
//小B同学帮我们做一个计算 在原数组的基础上增加1.5倍
int newCapacitv = oldCapacitv+(oldCapacitv>>1);//这里用到了位运算,效率比较高
//比较计算后的长度和所需的长度 如果计算出来的新数组的大小仍然不够用,那么久使用用户给定的数组的大小
if(newCapacitv-minCapacitv<0) {
newCapacitv = minCapacitv;
}
//调用小C同学,让他将创建新数组 将原数组中的元素移入新数组
elementDate =this.copyof(elementDate, newCapacitv);
}
//小C同学 负责将原数组中的元素给我然后移过去
private int[] copyof(int[] oldArray,int newCapacitv) {
//按照提供的新数组的长度,创建一个新数组
int [] newArray = new int[newCapacitv];
//将原数组中的元素存入新数组中
for(int i = 0;i<oldArray.length;i++) {
newArray[i] =oldArray[i];
}
return newArray;
}
//小D同学检测index是否合法
private void rangeCheck(int index) {
if(index <0 ||index>=size) {
//自定义一个异常 来说明问题
new BoxIndexOutOfBoundsException("index:"+index+"size"+size);
}
}
//用来将用户给定的element存储起来 参数类型为int类型,返回值类型为boolean类型的,告诉用户是否存储成功
public boolean add(int element) {
// TODO 自动生成的方法存根
//找一个别人做事 确保数组内部容量够用
this.ensureCapacitvInternal(size+1);//这行代码可以执行完毕,证明elemenDate肯定够用
//直接将新来的元素存入数组中 并且让size多一个记录
elementDate[size++]= element;
return true;
}
//用来将用户给定位置的的值返回给用户 参数是用户给定的索引位置,返回值类型是用户给定位置存储的值
public int get(int index) {
// TODO 自动生成的方法存根
//先找一个小D 来检测index是否合法
this.rangeCheck(index);//可以执行证明合法
//则找到index对应位置的值,返回
return elementDate[index];
}
//用来将用户给定位置的的值删除 参数是用户给定的索引位置,返回值类型是用户删除元素的值
public int remove(int index) {
// TODO 自动生成的方法存根
//通过调用小D同学来检测 index是否合法
this.rangeCheck(index);
//找到index位置的元素保留起来留给用户
int oldValue = elementDate[index];
for(int i =index;i<index-1;i++) {//从index开始到index-1位置结束,后面的元素向前覆盖
elementDate[i]=elementDate[i+1];
}
elementDate[--size] = 0;;
return oldValue;
}
//用来得到数组真实的长度(有效的个数),是私有方法来得到的,是安全的,不能主动修改的
public int size() {
// TODO 自动生成的方法存根
return size;
}
}
继承了这个Box类是为了封装抽象方法为之后要练习的LinkedBox做准备.
package Util;
public interface Box {
public boolean add(int element);
public int get(int index);
public int remove(int index);
public int size();
}
在检测index(地址)是否合法的时候定义了一个自定义异常.自定义异常用来输出错误信息.
package Util;
public class BoxIndexOutOfBoundsException extends RuntimeException{
public BoxIndexOutOfBoundsException() {}
public BoxIndexOutOfBoundsException(String msg) {
super(msg);
}
}