JAVA 自己实现一个ArrayList,详细解析

1.该类主要实现了ArrayList主要的几个方法:add()、remove()、size()、get()

package cn.sxt.oop.collection;
/**
 * 自己实现一个ArrayList
 * @author 2018-8-03
 * 主要方法:size()、add()、remove()、get()


public class ArrayListTest01 {

    //声明一个Object类型的数组
    private Object[] elementDate;
    //声明一个数组内元素个数
    private int size;

    public int size() {
        return size;
    }

    //定义一个无参构造函数,初始化数组内个数
    public ArrayListTest01(){
        this(10);//调用另一个构造方法(有参构造方法),所以,必须有一个有参构造方法
    }

    public ArrayListTest01(int initialCapacity) {//有参构造方法,实现数组容量的初始化
        if(initialCapacity<0) {
            try {
                throw new Exception();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        elementDate=new Object[initialCapacity];//初始化,容量为10    与前面的数组声明对应
    }
    //重点***********
    public void add(Object obj) {
        //首先,判断数组是否装满,是则扩容
        elementDate[size++]=obj;
        if(size==elementDate.length) {
            //创建一个新数组
            Object[] newArray=new Object[2*size+1];
            //将老数组拷贝到新数组内
            System.arraycopy(elementDate, 0, newArray, 0, elementDate.length);
            //再将新数组赋值给老数组
            elementDate=newArray;
        }
    }

    //get方法,得到数组实质就是一个数组的索引操作
    public Object get(int index) {
        //检查下标是否越界
        rangCheck(index);
        return elementDate[index];

    }

    public void remove(int index){  
        rangCheck(index);

         //删除指定位置对象,删除某位置,相当于 将后往前挪:
        int numMoved = size-index-1;
        if(numMoved>0){
            System.arraycopy(elementDate, index+1, elementDate, index, numMoved);
        }
    }
    public void remove(Object obj){
        for(int i=0;i<size;i++){
            if(get(i).equals(obj)){   //注意底层调用的equals方法而不是==。
                remove(i);
            }
        }
    }

    private void rangCheck(int index) {
        if(index<0||index>size) {
            try {
                throw new Exception();
            }catch(Exception e) {
                e.printStackTrace();
            }
        }

    }

    public void add(int index,Object obj) {
        rangCheck(index);
        ensureCapacity();//扩容
        System.arraycopy(elementDate,index,elementDate, index+1, size-index);
        elementDate[index]=obj;
        size++;
    }

    private void ensureCapacity() {
        if(size==elementDate.length) {
            Object[] newarray=new Object[size*2+1];
            System.arraycopy(elementDate, 0, newarray, 0, elementDate.length);
            elementDate=newarray;
        }

    }

    public static void main(String[] args) {
        ArrayListTest01 list=new ArrayListTest01();
        list.add("温暖");
        list.add("依然");
        list.add("wk");
        list.add("wk1");
        list.add("wk2");
        System.out.println("list内拥有:"+list.size()+"个元素");
    }
}

2.涉及知识点
① 数组声明与创建
数组声明:数组在使用前需要先声明,指定数组中存放的数据类型和名字,本文应用如下:

private Object[] elementDate;

数组创建:数组声明后,需要创建才能使用。创建数组就是指定数组可以存放的数据(元素),并分配对应大小的内存空间。本文应用如下

elementDate=new Object[initialCapacity];

②this方法的用法
主要有三种用法:
⑴ 使用this关键字引用成员变量
⑵ 使用this关键字引用成员方法
⑶ 使用this关键字在自身构造方法内部引用其它构造方法
提示:this关键字代表自身类的对象(实例)
本文应用如下:

public ArrayListTest01(){
        this(10);//上面方法⑶的应用,调用下面的有参构造方法
    }

    public ArrayListTest01(int initialCapacity) {
        if(initialCapacity<0) {
            try {
                throw new Exception();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        elementDate=new Object[initialCapacity];
    }

③“==”的用法
两种主要用途:
⑴比较基本数据类型(byte、short 、int、long、float、double、char、boolean)
== 表示数量相等(值相等),由于不是对象,所以不能使用equals()方法,
⑵比较符合数据类型(类)
== 比较的是他们在内存中的地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。

public void add(Object obj) {
        elementDate[size++]=obj;
        if(size==elementDate.length) {//上面方法(1)的应用,比较的是基本类型
            Object[] newArray=new Object[2*size+1];
            System.arraycopy(elementDate, 0, newArray, 0, elementDate.length);/
            elementDate=newArray;
        }
    }

④ equal()的用法
⑴ 对于字符串来说是比较内容的
⑵ 对于非字符串来说是,比较其指向的对象是否相同。

public void remove(Object obj){
        for(int i=0;i<size;i++){
            if(get(i).equals(obj)){   //注意底层调用的equals方法而不是==。
            //比较的是两个对象的值是否相等,不是地址
                remove(i);
            }
        }
    }

⑤ 异常处理
Java的“异常”处理是通过try、catch、throw、throws和finally5个关键字来实现的。
⑴ try…catch..方法的使用
把可能引发异常的代码放进一个try块中,try块后面应包含一个或多个catch子句来指定用户想要捕捉的“异常”的类型。
⑵ throw抛出异常的使用(注意与throws对比,区别)

private void rangCheck(int index) {
        if(index<0||index>size) {
            try {
                throw new Exception();//throw 抛出具体的异常
            }catch(Exception e) {
                e.printStackTrace();
            }
        }

⑥ 还用到方法字符串拷贝权限修饰符基本数据类型的使用等相关知识。

3. 思考与体会

1.ArrayList底层实现是基于数组实现的。所以,获取元素时,就是利用数组的下标索引返回目标对象,故,其查询速度比较快。如下:

public Object get(int index) {
        //检查下标是否越界
        rangCheck(index);
        return elementDate[index];//采用数组的下标索引

    }

2.ArrayList自动改变大小的功能其实就是数组的拷贝问题。

具体操作可以分为以下几步:
判断数组是否装满
②装满就创建一个新的数组,该新数组是原来数组的2倍加1(源码就是如此,我们自己设计时,可以自行决定)
③将老数组的内容拷贝到新数组中,
④再将新数组赋值给老数组名(以便重复使用老数组名字)
这样不断循环,就实现了数组的不断扩容。

public void add(Object obj) {
        //①首先,判断数组是否装满,是则扩容
        elementDate[size++]=obj;
        if(size==elementDate.length) {
            //②创建一个新数组
            Object[] newArray=new Object[2*size+1];
            //③将老数组拷贝到新数组内
            System.arraycopy(elementDate, 0, newArray, 0, elementDate.length);
            //④再将新数组赋值给老数组
            elementDate=newArray;
        }
    }

3. 难点与重点
掌握add()和remove()。

该实现类,还不够完善,但是,对于我们理解ArrayList的原理和后续看其源码有很大的帮助。

  • 11
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值