自己建立动态数组
动态数组的数据封装在Array中自己定义的data静态数组中
首先创建一个自定义的静态数组,并且向其中添加自己想要实现的方法,如添加元素,获取容量,查找元素等
创建初始的静态数组,代码如下
public class Array {
private int[] data;
private int size;//不让用户随意改动
//构造函数,传入数组的容量 capability构造Array
public Array(int capacity) {
data = new int[capacity];
size = 0;
}
//提供默认构造函数,默认数组容量capability = 10
public Array() {
this(15);
}
}
为此静态数组添加方法:
public class Array {
private int[] data;
private int size;//不让用户随意改动
//构造函数,传入数组的容量 capability构造Array
public Array(int capacity) {
data = new int[capacity];
size = 0;
}
//提供默认构造函数,默认数组容量capability = 10
public Array() {
this(15);
}
//用户查询数组的元素量size
public int getSize() {
return size;
}
//获取数组的容量:length
public int getCapacity() {
return data.length;
}
//返回数组是否为空
public boolean isEempty() {
return size == 0;
}
//向数组最开始添加元素
public void addFirst(int e) {
add(0,e);
}
//向数组最后添加元素
public void addLast(int e) {
if(size == data.length) {
throw new IllegalArgumentException("addLast failed Array is full");
}
//add(size,e);
data[size] = e;
size++;
}
//向指定位置添加元素,将插入索引位置后的元素向后挪
public void add(int index , int e) {
if(size == data.length) {
throw new IllegalArgumentException("addLast failed Array is full");
}
if(index<0||index>size) {//index==size相当于在最后插入元素
throw new IllegalArgumentException("Add failed . require index>=0 and index<=size");
}
for(int i = size-1;i>=index;i--) {
data[i+1] = data[i];
}
data[index] = e;
size++;
}
//获取index索引位置的元素,使用如此封装的方法的好处:用户永远无法查询未使用的空间(查询元素)
int get(int index) {
if(index<0||index>=size)
throw new IllegalArgumentException("Get failed.index is illegal");
return data[index];
}
//将某个元素改变为元素e(修改元素)
void set(int index,int e) {
if(index<0||index>=size)
throw new IllegalArgumentException("Set failed.index is illegal");
data[index] = e;
}
@Override
public String toString() {
//拼接一个字符串
StringBuilder res = new StringBuilder();
res.append(String.format("Array:size = %d,capacity = %d\n",size,data.length));
res.append("[");
for(int i = 0;i<size;i++) {
res.append(data[i]);
if(i!=size - 1) {
res.append(", ");
}
}
res.append("]");
return res.toString();//因为是StringBuilder
}
//是否包含某个元素
public boolean contains(int e) {
for(int i = 0;i<size;i++) {//(这里是最简单的遍历)
if(data[i]==e) {
return true;
}
}
return false;
}
//找到元素对应的索引位置,如果不存在元素则返回-1
public int find(int e) {
for(int i = 0;i<size;i++) {
if(data[i]==e) {
return i;
}
}
return -1;
}
//删除指定位置元素(并且返回此元素)(有指定索引)元素都向左移(size--,但是用户看不到size上有值的影响 )
public int remove(int index) {
if(index<0||index>=size) {
throw new IllegalArgumentException("Remove failed.index is illegal");
}
int ret = data[index];
for(int i = index+1 ;i<size;i++) {
data[i-1] = data[i];
}
size--;
return ret;
}
//删除第一个元素,返回删除的元素
public int removeFirst() {
return remove(0);
}
//删除最后一个元素
public int removeLast() {
return remove(size-1);
}
//删除所有e
public void removeAll(int e) {
while(find(e)!=-1) {
removeElement(e);
}
}
//删除是否具有的某个元素
public void removeElement(int e) {
int index = find(e);
if(index!=-1) {
remove(index);
}
}
}
当前数组类的最大问题是只能适用于int变量使用泛型:使其可以放置任意类型的数据(包括自定义的类型)(非基本数据类型)但是基本数据类型都有对应的包装类
将数组改造成泛型数组
在resize()中
开一个更大的数组,将data数组里的数据复制进newdata
使data指向newdata
public class Array <T>{//这里的T可以换成自定义的其他名称
public Array(int capacity) {
data = (T[])new Object[capacity];//强制类型转换为T[]型数组,Object类是所有类的父类
size = 0;
}
}
--改造函数:改变部分函数返回值类型和参数类型
进一步修改为动态数组:
public class Array <T>{//这里的T可以换成自定义的其他名称
private T[] data;
private int size;//不让用户随意改动
//构造函数,传入数组的容量 capability构造Array
public Array(int capacity) {
data = (T[])new Object[capacity];//强制类型转换为T[]型数组,Object类是所有类的父类
size = 0;
}
//提供默认构造函数,默认数组容量capability = 10
public Array() {
this(10);
}
//用户查询数组的元素量size
public int getSize() {
return size;
}
//获取数组的容量:length
public int getCapacity() {
return data.length;
}
//返回数组是否为空
public boolean isEempty() {
return size == 0;
}
//向数组最开始添加元素
public void addFirst(T e) {
add(0,e);
}
//向数组最后添加元素
public void addLast(T e) {
if(size == data.length) {
throw new IllegalArgumentException("addLast failed Array is full");
}
//add(size,e);
data[size] = e;
size++;
}
//向指定位置添加元素,将插入索引位置后的元素向后挪
public void add(int index , T e) {
if(index<0||index>size) {//index==size相当于在最后插入元素
throw new IllegalArgumentException("Add failed . require index>=0 and index<=size");
}
if(size >= data.length) {
resize(data.length*2);//扩容
}
for(int i = size-1;i>=index;i--) {
data[i+1] = data[i];
}
data[index] = e;
size++;
}
//获取index索引位置的元素,使用如此封装的方法的好处:用户永远无法查询未使用的空间(查询元素)
T get(int index) {
if(index<0||index>=size)
throw new IllegalArgumentException("Get failed.index is illegal");
return data[index];
}
//将某个元素改变为元素e(修改元素)
void set(int index,T e) {
if(index<0||index>=size)
throw new IllegalArgumentException("Set failed.index is illegal");
data[index] = e;
}
@Override
public String toString() {
//拼接一个字符串
StringBuilder res = new StringBuilder();
res.append(String.format("Array:size = %d,capacity = %d\n",size,data.length));
res.append("[");
for(int i = 0;i<size;i++) {
res.append(data[i]);
if(i!=size - 1) {
res.append(", ");
}
}
res.append("]");
return res.toString();//因为是StringBuilder
}
//是否包含某个元素
public boolean contains(T e) {
for(int i = 0;i<size;i++) {//(这里是最简单的遍历)
if(data[i]==e) {
return true;
}
}
return false;
}
//找到元素对应的索引位置,如果不存在元素则返回-1
public int find(T e) {
for(int i = 0;i<size;i++) {
if(data[i]==e) {
return i;
}
}
return -1;
}
//删除指定位置元素(并且返回此元素)(有指定索引)元素都向左移(size--,但是用户看不到size上有值的影响 )
public T remove(int index) {
if(index<0||index>=size) {
throw new IllegalArgumentException("Remove failed.index is illegal");
}
T ret = data[index];
for(int i = index+1 ;i<size;i++) {
data[i-1] = data[i];
}
size--;
if(size<=data.length/4&&data.length/2!=0) {
resize(data.length/2);
}
//data[size]=null;//使java垃圾回收机制可以将此对象回收
return ret;
}
//删除第一个元素,返回删除的元素
public T removeFirst() {
return remove(0);
}
//删除最后一个元素
public T removeLast() {
return remove(size-1);
}
//删除所有e
public void removeAll(T e) {
while(find(e)!=-1) {
removeElement(e);
}
}
//删除是否具有的某个元素
public void removeElement(T e) {
int index = find(e);
if(index!=-1) {
remove(index);
}
}
private void resize(int newCapacity) {
T[] newdata =(T[]) new Object[newCapacity];
for(int i = 0;i<size;i++) {
newdata[i] = data[i];
}
data = newdata;
}
}