自定义动态数组模拟ArrayList
- 自定义接口
抽象出这个类所有的功能
package ArrayListTest;
//封装数组的集合接口,zhi存储字符串
public interface MyList {
void add(String str);//向集合末尾添加字符串
void add(int index,String str);//zai指定位置添加字符串
String remove(int index);//删除指定位置的字符串
void remove(String str);//删除指定内容的字符串 从头查找删一个
String get(int index);//获得指定位置的元素
String set(int index,String str);//将指定位置的字符串修改为这个字符串,返回删除前的元素
int size();//获取当前数组的长度
}
- 定义MyArrayList类且实现MyList接口
package ArrayListTest;
//封装一个数组,这个数组比实际的大一点
/* 这个数组用于存储添加的元素
* 指定一个属性代表存储元素的末尾;这个是真实大小
*
* */
public class MyArrayList implements MyList {
private int size;//数组中元素的个数
int arraySize=10;//数组的长度
String [] array;
@Override
public void add(String str) {
// TODO Auto-generated method stub
//判断是否需要扩容
//如果需要扩容,创建一个新的数组,长度为原数组的50%
//将原数组的内容复制到新数组
//将参数 str添加到size位置 size++
if(size==0) {
array=new String[arraySize];
}
if(size>=array.length) {
String [] newArray=new String[array.length+(array.length>>1)];
System.arraycopy(array, 0, newArray,0 , array.length);
array=newArray;
}
array[size]=str;
size++;
}
@Override
public void add(int index, String str) {
// TODO Auto-generated method stub
if(size>=array.length) {
String [] newArray=new String[array.length+(array.length>>1)];
System.arraycopy(array, 0, newArray, 0, array.length);
array=newArray;
}
if(index>=size)
System.out.println("越界异常");
for(int i= size-1;i>=index;i--) {
array[i+1]=array[i];
}
array[index]=str;
}
@Override
public String remove(int index) {
// TODO Auto-generated method stub
//整体前移 size-- size位置给null
String str=array[index];
for(int i=index;i<size-1;i++) {
array[i]=array[i+1];
array[size]=null;
size--;
}
return str;
}
@Override
public void remove(String str) {
// TODO Auto-generated method stub
for(int i=0;i<size;i++) {
if(array[i].equals(str)) {
remove(i);
break;
}
}
}
@Override
public String get(int index) {
// TODO Auto-generated method stub
return array[index];
}
@Override
public String set(int index, String str) {
// TODO Auto-generated method stub
String s=array[index];
array[index]=str;
return s;
}
@Override
public int size() {
// TODO Auto-generated method stub
return size;
}
}
3.测试类
package ArrayListTest;
public class MyArrayListTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyArrayList a=new MyArrayList();
a.add("你爹爹");
int s=a.size();
System.out.println(s);
}
}
空指针异常的出现成因
1.编写抽象类接口
package ArrayListTest2;
public interface MyList {
void add(String str);//添加元素
void add(int index,String str);//按下标添加元素
void remove(String str);//按字符串删除元素
void remove(int index);//按下标删除元素
int size();//返回存储元素的实际大小
void getStr();//遍历当前字符串
}
2.编写自定义MyArrayList类
成员变量中;创建空的数组String array[];
默认值为null
在自定义类MyListArray中;
if(size==0){
String array []=new String[arraySize];
}
这个中创建的数组array不赋值给成有关变量;会造成之后的空指针异常;看底层源码发现这个array的前身是成员变量中的array。
package ArrayListTest2;
public class MyListArray implements MyList {
private int size;
int arraySize=15;
String array [];//创建了一个为null的空数组;
@Override
public void add(String str) {
// TODO Auto-generated method stub
if(size==0) {
String array[]=new String [arraySize];//String array [] =new String[arraySize] 在14行会报空指针异常;需要把这个新建的类赋值给 array
}
if(size>=array.length) {//出现过空指针异常 直接点源码发现这个array是成员变量中的array 为空;运行程序会报出空指针异常
String newArray[]=new String[array.length+10];
for(int i=0;i<array.length;i++) {
newArray[i]=array[i];
}
array=newArray;
}
array[size]=str;
size++;
}
@Override
public void add(int index, String str) {
// TODO Auto-generated method stub
if(size==0) {
String array[]=new String [arraySize];
}
if(size>=array.length) {
String newArray[]=new String[array.length+10];
for(int i=0;i<array.length;i++) {
newArray[i]=array[i];
}}
for(int i=size-1;i>=index;i--) {
array[i+1]=array[i];
}
array[index]=str;
size++;
}
@Override
public void remove(String str) {
// TODO Auto-generated method stub
if(size==0) {
String array[]=new String [arraySize];
}
if(size>=array.length) {
String newArray[]=new String[array.length+10];
for(int i=0;i<array.length;i++) {
newArray[i]=array[i];
}}
}
@Override
public void remove(int index) {
// TODO Auto-generated method stub
if(size==0) {
String array[]=new String [arraySize];
}
if(size>=array.length) {
String newArray[]=new String[array.length+10];
for(int i=0;i<array.length;i++) {
newArray[i]=array[i];
}}
for(int i=index;i<size-1;i++) {
array[i]=array[i++];
}
array[size-1]=null;
size--;
}
@Override
public int size() {
// TODO Auto-generated method stub
return size;
}
@Override
public void getStr() {
// TODO Auto-generated method stub
}
}
3.测试类
package ArrayListTest2;
public class MyArrayListTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyListArray a=new MyListArray();
a.add("我是你爸爸");
a.add("快叫爸爸");
int s=a.size();
System.out.println(s);
}
}
//结果
/*
Exception in thread "main" java.lang.NullPointerException: Cannot read the array length because "this.array" is null
at ArrayListTest2.MyListArray.add(MyListArray.java:14)
at ArrayListTest2.MyArrayListTest.main(MyArrayListTest.java:8)
*/
自定义类更改返回值类型;接口的抽象方法也要改返回值类型
1.接口
getsize();的返回值类型错了
在自定义类中;覆写会报错;更改返回值也错;需要更改接口
package ArrayListTest3;
public interface MyList {
void add(String str);
void add(int index,String str);
void remove(int index);
void remove(String str);
void getSize();
}
定义类
引用指向未删除的问题
remove中;删除一个元素;需要从前往后整体向前移动一步;
最后一位size-1向前移动一位;删除的位置被后面的覆盖到达删除的目的;但是在最后一位 及size-1的下标位置;向前移动;其本身引用指向的内容并未被覆盖;需要手动 array[size-1]=null垃圾回收掉
1.定义抽象类接口
package ArrayListTest3;
public interface MyList {
void add(String str);
void add(int index,String str);
void remove(int index);
void remove(String str);
int getSize();
}
2.自定义ArrayList类
* remove方法中没有回收前移造成的 size-1的位置未被覆盖;引用指向未回收垃圾及未写 array[size-1]=null;
public void remove(int index){
for(int i=index;i<size-1;i++){
array[i]=array[i+1];
}
}
package ArrayListTest3;
public class ArrayList implements MyList {
private int size;
int arraySize;
String array[];
public ArrayList() {
arraySize=3;
}
public void add(String str) {
// TODO Auto-generated method stub
if(size==0) {
array=new String[arraySize];
}
if(size>=array.length) {
String newArray []=new String[array.length+10];
for(int i=0;i<array.length;i++) {
newArray[i]=array[i];
}
array=newArray;
}
array[size++]=str;
}
@Override
public void add(int index, String str) {
// TODO Auto-generated method stub
if(size==0) {
array=new String[arraySize];
}
if(size>=array.length) {
String newArray [] =new String[array.length+8];
for(int i=0;i<array.length;i++) {
newArray[i]=array[i];
}
array=newArray;
}
for(int i=size-1;i>=index;i--) {
array[i+1]=array[i];
}
array[index]=str;
size++;
}
@Override
public void remove(int index) {
// TODO Auto-generated method stub
if(size==0) {
array=new String [arraySize];
}
if(size>=array.length) {
String newArray []=new String[array.length+10];
for(int i=0;i<array.length;i++) {
newArray[i]=array[i];
}
array=newArray;
}
for(int i=index;i<size-1;i++) {
array[i]=array[i+1];
}
//array[size-1]=null; 未回收元素最后指向前移 引用未回收的问题
size--;
}
@Override
public void remove(String str) {
// TODO Auto-generated method stub
for(int i=0;i<array.length;i++) {
if(array[i].equals(str)) {
remove(i);
}
}
}
@Override
public int getSize() {
// TODO Auto-generated method stub
return size;
}
public void getArray() {
for(String s_:array) {
System.out.println(s_);
}
}
public void getIndex(int index) {
System.out.println(array[index]);
}
}
测试类
package ArrayListTest3;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList a=new ArrayList();
a.add("如果我是你爹");
a.add("给我钱");
a.add("叫爸爸");
a.remove(1);
System.out.println(a.getSize());
a.getIndex(2);//未回收size-1前移动后;这个位置没有被后者覆盖;引用指向未变
a.getIndex(1);
}
}
//结果
/*
2
叫爸爸//本不应存在的一个值
叫爸爸
*/