动态数组及泛型
动态数组
固定数组存在长度一旦初始化就无法修改的缺陷,新增、插入元素会受容量限制,因此需要手动封装动态数组,基于原生定长数组实现自动扩容、增删改查功能。
动态数组的方法
- 末尾添加数据:数组长度 + 1,原数组全部元素复制,末尾存放新数据
- 指定位置插入:插入位置前元素不变,插入位置存放新元素,后面元素统一后移一位
- 删除指定位置数据:删除位置之后的元素统一向前覆盖一位,数组长度 - 1
- 删除指定数据(使用布尔类型):遍历找到第一个匹配下标,调用按下标删除方法
- 删除所有相同数据:循环执行单次数据删除,直到不存在目标元素
example
自定义动态数组 ArrList 完整实现代码
packagecom.yw.oop0627;/** * @author YAN * @date 2026/6/27 17:36 * @description 动态数组 */publicclassArrList{//初始数组privateint[]arr=newint[0];//末尾添加数据publicvoidadd(intdata){//扩容原数组int[]nArr=newint[arr.length+1];nArr[arr.length]=data;//拷贝原数组数据到新数组for(inti=0;i<arr.length;i++){nArr[i]=arr[i];}//更新对象头arr=nArr;}//插入数据publicvoidinsert(intindex,intdata){int[]newArr=newint[arr.length+1];//复制插入位置之前的数据for(inti=0;i<index;i++){newArr[i]=arr[i];}//插入目标数据newArr[index]=data;//复制插入位置之后的数据for(inti=index;i<arr.length;i++){newArr[i+1]=arr[i];}arr=newArr;}//删除指定位置数据,返回被删除的数据publicintremove(intindex){//保存要删除的元素intdelNum=arr[index];int[]newArr=newint[arr.length-1];//复制删除位置前数据for(inti=0;i<index;i++){newArr[i]=arr[i];}//删除位置后数据向前移动for(inti=index;i<newArr.length;i++){newArr[i]=arr[i+1];}arr=newArr;returndelNum;}//删除指定数据(使用布尔类型)publicbooleanremoves(intdata){for(inti=0;i<arr.length;i++){if(arr[i]==data){remove(i);returntrue;}}returnfalse;}//删除所有相同数据publicbooleanremoveAll(intdata){booleanflag=false;//循环删除,直到没有目标数据while(removes(data)){flag=true;}returnfalse;}//获取数据publicintget(intindex){//判断index是否合法returnarr[index];}//长度publicintsize(){returnarr.length;}publicstaticvoidmain(String[]args){//测试ArrListlist=newArrList();list.add(1);list.add(2);list.add(3);for(inti=0;i<list.size();i++){System.out.print(list.get(i)+" ");}System.out.println("\n插入元素5到下标1位置:");list.insert(1,5);for(inti=0;i<list.size();i++){System.out.print(list.get(i)+" ");}System.out.println("\n删除下标2位置元素:"+list.remove(2));for(inti=0;i<list.size();i++){System.out.print(list.get(i)+" ");}}}动态数组的局限性
由于底层依然使用固定长度的 int 数组存储数据,因此只能添加整形数据,怎么怎么优化动态数组,让其能添加任何类型?
可使用object的数组
局限性:不同类型数据都混在一起
解决:使用泛型
规避耗时问题:减少拷贝次数,对原数组进行2倍扩容
example
packagecom.yw.oop0702;/** * @author YAN * @date 2026/7/2 18:50 * @description */publicclassArrList<E>{//初始数组privateObject[]arr;privatestaticintlen=10;//动态数组的默认初始长度privateintsize=0;//记录有效数据个数//构造方法初始化数组长度publicArrList(intlen){arr=newObject[len];}//设置长度publicArrList(){//构造方法相互调用:this(参数,,);this(len);}//末尾添加数据publicvoidadd(Ee){//判断是否需要扩容if(size==arr.length){//对原数组2倍扩容Object[]nArr=newObject[arr.length*2];//拷贝愿数组数据到新数组for(inti=0;i<arr.length;i++){nArr[i]=arr[i];}//更新对象头arr=nArr;}arr[size]=e;size++;}//插入数据publicvoidinsert(intindex,Ee){//优先扩容if(size==arr.length){Object[]nArr=newObject[arr.length*2];//拷贝愿数组数据到新数组for(inti=0;i<arr.length;i++){nArr[i]=arr[i];}//更新对象头arr=nArr;}//后移元素for(inti=size;i>index;i--){arr[i]=arr[i-1];}arr[index]=e;size++;}//删除指定位置数据,返回被删除的数据publicEremove(intindex){//把要删除位置的元素提前存起来EdeleteElement=(E)arr[index];//使用当前的泛型符号//元素前移覆盖for(inti=index;i<size-1;i++){arr[i]=arr[i+1];}//最后的位置为空arr[size-1]=null;//有效元素个数-1size--;//返回最开始保存的、被删除的元素returndeleteElement;}//删除指定数据publicbooleanremoves(Ee){for(inti=0;i<size;i++){if(arr[i].equals(e)){remove(i);returntrue;}}returnfalse;}//删除所有相同publicbooleanremoveAll(Ee){for(inti=size-1;i>=0;i--){if(arr[i].equals(e)){remove(i);returntrue;}}returnfalse;}//获取数据publicEget(intindex){//判断index是否合法return(E)arr[index];}//长度publicintsize(){returnsize;}publicstaticvoidmain(String[]args){//测试ArrList<Integer>list=newArrList<>();longstart=System.currentTimeMillis();for(inti=0;i<100000;i++){list.add(i);}longend=System.currentTimeMillis();System.out.println("耗时:"+(end-start));//测试插入list.insert(0,999);//测试删除list.remove(0);//测试删除指定元素list.removes(50000);System.out.println("当前有效元素个数:"+list.size());}}关于基本类型的对应包装类
基本数据类型 -> 包装类(java.lang 包下)
byte -> Byte
short -> Short
int -> Integer
long -> Long
float -> Float
double -> Double
char -> Character
boolean -> Boolean
关于Java内置动态数组ArrayList扩容机制
- 底层原理
ArrayList 底层基于 Object [] 数组实现,属于动态数组。
// 默认初始容量:10privatestaticfinalintDEFAULT_CAPACITY=10;// 空数组常量(懒加载:无参构造初始化时不创建长度为10的数组,先赋值空数组,第一次add才初始化容量10)privatestaticfinalObject[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA={};// 底层存储数组transientObject[]elementData;// 集合中实际存储的有效元素个数privateintsize;- 三种构造方法
- 无参构造
publicArrayList(){// 初始化空数组,懒加载,首次添加元素才扩容到10elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}- 指定初始容量构造
publicArrayList(intinitialCapacity){if(initialCapacity>0){elementData=newObject[initialCapacity];}elseif(initialCapacity==0){elementData=EMPTY_ELEMENTDATA;}else{thrownewIllegalArgumentException("Illegal Capacity: "+initialCapacity);}}- 集合参数构造:把其他集合转为 ArrayList
泛型<>
作用:把添加的数据形参化,限制相同类型的数据才能被添加到同一个集合对象
注:确定泛型的数据类型时必须是引用类型
常用泛型符号:
E T K V…(任意大写字母即可,E更为常用)