从我开始接触各种编程语言,最常用最简单的数据结构就是数组啦!但是我们用着用着就会发现它的局限性,在使用过程中它的长度是不变的,就会有时限制我们的需求。那就会想到怎么让它可变呢?变得灵活呢?JAVA中已经有一个封装好的可以直接使用的API——ArrayList,就是一种动态数组,但是下面我们要自己用数组实现一个动态数组,直接满足我们的需求。
一.在实现之前,先给大家做些准备工作
1.要怎么实现动态数组呢?
首先先向内存申请开辟一段空间,也就是一个定长数组,长度假设为len,定义一个计数的count,记录当前已用的空间,就是动态数组的长度,将count与len比较,如果count>len ,就新开启一个len*size(这里size为扩展因子,每次空间不足的时候就扩展size倍)长的定长数组,把原来数组中元素都添加到新数组中,再放入新的元素,如果count<len,直接在原来的定长数组内添加数据就可以
2.可以实现哪些功能呢?
·获取当前动态数组的长度
·动态添加元素add
·获取指定位置的元素get
·在任意位置插入元素insert
·在任意位置删除元素delete
3.在实现过程中要注意什么?
·可以将待添加的元素设置为Object类,Objtec是所有类父类,可以添加任意类型的元素。
·有时我们需要添加的元素类型只有一种,而有时又需要添加多种元素类型,这时就需要使用泛型,它不是基本的数据类型,只是一个特殊的符号,指JAVA任意一种引用类型。
具体JAVA实现代码如下
package com.hash;
public class DynamicArray<E> {
//申请一个数组,初始定长是100
Object[] Original;
private int startLength=100;
int len=0;//当前长度
//不给数组的初始长度,使用默认的初始长度
public DynamicArray(){
Original = new Object[startLength];
}
//给定初始数组长度
public DynamicArray(int startLength){
this.startLength=startLength;
}
//添加数据的方法
public void add(E o){
if(len==Original.length){
//将数组的长度扩展一倍
Object[]newArray=new Object[Original.length*2];
//保存原来的值
for(int i=0;i<len;i++){
newArray[i]=Original[i];
}
newArray[len]=o;
//把改变后的数组赋值给原来的数组
Original=newArray;
}
else{
Original[len]=o;
len++;
}
}
//返回数组的长度
public int size(){
return len;
}
//获取指定位置的数据
public Object get(int index){
return (E)Original[index];
}
//在指定位置插入数据
public void insert(E o,int index){
len++;
if(len==Original.length){
Object[] newArray=new Object[Original.length*2];
for(int i=0;i<index;i++)
newArray[i]=Original[i];
for(int i=index+1;i<len;i++)
newArray[i]=Original[i-1];
newArray[index]=o;
Original=newArray;
}
else{
for(int i=len-1;i>=index;i--){
Original[i+1]=Original[i];
}
Original[index]=o;
}
}
//删除指定位置数据的方法
public Object delete(int index){
len--;
//保存要删除的元素
Object ele=Original[index];
//从删除数据位置开始,从后往前替换
for(int i=index;i<len;i++){
Original[i]=Original[i+1];
}
return ele;
}
public static void main(String[] args) {
DynamicArray test=new DynamicArray();
test.add(1);
test.add(2);
test.add(3);
System.out.println("lenghth:"+test.size());
test.insert(4, 1);
test.insert(5, 0);
test.delete(3);
for(int i=0;i<test.size();i++){
System.out.print(test.get(i)+" ");
}
}
}
运行结果如下
lenghth:3
5 1 4 3
最后 总结一下
·我把方法的返回值类型都设置成了Object类,它是所有类型的父类,可以代替任何类型。
在获取指定位置的数据返回数据时,因为是Object父类转化为E子类,是自动转化的,就是下面部分
public Object get(int index){
return Original[index];//不需要转化
}
·这里当元素个数超过定长数组的长度的时候,我直接让扩展因子为2,每次扩大一倍,这样做降低了算法的时间复杂度,如果每次扩展一个大小,那么就可能总会重新创建数组,会变得麻烦。