[JAVA]集合框架之自己实现一个具有基本增查删改功能的ArrayList

ArrayList的介绍

ArrayList故名意思就是动态数组的意思,它具备了数组的基本属性,除此之外,提供了动态的增加和减少元素,灵活的设置数组的大小等好处.


ArrayList的实现

ArrayList实现了List的接口,底层使用数组来保存其中的元素.了解到这些信息我们我们可以自己实现一个简单的ArrayList

一 .私有属性定义

在ArrayList中我们只需要定义两个私有属性,分别为保存元素的数组和这个数组的长度

private  Object[] elementData;//这是一个对象数组! 外部调用需要new
private int size; // 全局变量默认值是0;size是元素的数量,不是容器的容量大小

二 . 数组的初始化

数组的初始化直接写在构造器中,其他没有什么好讲的,请直接看代码

// 无障碍阅读友情提示:initialCapacity=总容量
public MyArrayList(int initialCapacity) {
            //如果创建的长度小于零抛异常(数组长度应该大于等于0)
        if (initialCapacity < 0) {
            try {
                throw new Exception();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //创建新的数组
        this.elementData = new Object[initialCapacity];
    }

这里还可以简单优化一下,创建一个无参构造器来调用上面的有参构造器

    public MyArrayList() {
        //调用上面的有参构造器
        this(10);
    }

这样每次new 这个对象不用在构造函数里写数组的长度了,起步就是10个;

三 . 数组容量检测

需要数组扩容前必定检测数组的长度,所以这一步也必不可少.

private boolean sizeCheck(){
        if (size > elementData.length - 1) // 假设length是10 size是10的情况已经满了
        return false;
                return true;
    }

四 . 扩容原理

因为ArrayList和数组的最大区别就是数组长度一旦定义便不可修改,而ArrayList比较牛逼,可以实现数组长度的改变.但实现原理真的很简单,一句话概括就是“临时创建一个长度更长的数组,将原数组的元素拷贝进新的数组,再将这个新数组赋值给原数组”如果第一次读比较拗口,多读几遍就会明白原来实现是真的很简单.我还没亮出代码,代码可能就浮现在你的脑海之中了.但是我还是要强行贴上代码

    private void increaseCapacity(){
        //创建一个是原来数组中元素个数?2容量的数组(注意区分数组元素个数和数组长度)
        Object[] newArray = new Object[size * 2];
        //下面提供两种元素拷贝的方法,一种是自己for循环赋值,一种直接用数组拷贝函数
        // for(int i=0;i<elementData.length;i++){
        // newArray[i]=elementData[i];
        // }
        // elementData=newArray;
        System.arraycopy(elementData, 0, newArray, 0, elementData.length);
        //后排提示 忘了这步可就前功尽弃了
        elementData = newArray;
    }

五 . 常用方法

因为实现了List的接口,ArrayList也理应具有List的方法,这里给出几个较为常用的方法.

0.输入索引范围检查

因为增删查该都涉及输入的数组下标;所以应该有一个输入数组下标合法性的检查

 private void rangeCheck(int index){
     if(index>=size){ //index从0开始 比size小   size本来就大于零;
            try {
                throw new Exception();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

 }

1.元素的插入

    public void add(Object obj) {
                    //检查是否需要扩容
        if(sizeCheck()==false){
             increaseCapacity();
        }
          //增加新的元素,注意size也要增加
       elementData[size++] = obj;
    }

2 元素的查找

① 输入一个索引,返回该索引对应的元素
    public Object  get(int index){
        rangeCheck(index);
        return elementData[index];

    }
② 输入一个元素,返回从前往后遇到的第一个此元素的索引;若找不到则返回-1;
        public int get(Object obj){
        for(int i=0;i<size;i++){
        if(obj.equlas(elementData[i]))
        return i;
       }
        return -1;
}

3.元素的删除

① 删除输入索引所对应的元素

删除的原理就是把索引对应的元素删除,该索引以后的元素全都往前挪移一位
移动元素有两种方法如下1 for循环自己移动 2 借助数组拷贝函数

public void remove(int index)   {  // 当索引为 2的时候 i 0 1 2 3 4 
      rangeCheck(index);
     for(int i=index;i<size-1;i++){
         elementData[i]=elementData[i+1]; // i 0 1 3 4 4 
     }
    // System.arraycopy(elementData,index+1, elementData, index, size-(index+1));   index从0开始
     elementData[--size]=null;// 最后一个元素是elementData[size-1] =null 同时 size减一,此时size=4
 }
② 输入一个元素,删除从前往后遇到的相同的第一个此元素.如果没有遇到就不做修改.
 public void remove(Object obj){
    for(int i = 0; i<size;i++){
    if (obj.equals(elementData[i])){
    //调用数组复制函数
    System.arraycopy(elementData,i+1, elementData, i, size-(i+1));
             elementData[--size]=null;
         } 
     }
 }

4.元素的插入

① 输入一个元素和插入到数组的位置
 public void insert(Object obj,int index){
     //输入数组下标合法性判断
     rangeCheck(index);
     //判断插入前数组是否已经满了
     if(sizeCheck()==false){
         increaseCapacity();
    }
    //把索引位置腾出来(元素向后移动)
     for(int i=index;i<size;i++){
        elementData[i+1]=elementData[i];
    }
    //插入元素
     elementData[index]=obj;
 }

最后总结

无论是ArrayList的原理还是实现方法都是比较简单的,自己多加思索就可以实现其中的增查删改功能, 静下心来看看ArrayList源码后自己实现一个有基本功能的动态数组,无论是对自身的思维方式还是代码能力都有很大的提升.


最后的最后附上源码(凑篇幅???)

public class MyArrayList {
    private Object[] elementData;// 这是一个对象数组!
        private int size; // 全局变量默认值是0;size是元素的数量,不是容器的容量大小

    public MyArrayList(int initialCapacity) {
        if (initialCapacity < 0) {
            try {
                throw new Exception();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        this.elementData = new Object[initialCapacity];
    }

    public MyArrayList() {
        this(10);
    }

    public void add(Object obj) {
        if (sizeCheck() == false) {
            increaseCapacity();
        }
        elementData[size++] = obj;
    }

    private boolean sizeCheck() {
        if (size > elementData.length - 1) // length是10 size是10的情况已经满了
            return false;
        return true;
    }

    private void increaseCapacity() {
        Object[] newArray = new Object[size * 2];
        // for(int i=0;i<elementData.length;i++){
        // newArray[i]=elementData[i];
        // }
        // elementData=newArray;
        System.arraycopy(elementData, 0, newArray, 0, elementData.length);
        elementData = newArray;
    }

    public Object get(int index) {
        rangeCheck(index);
        return elementData[index];

    }

    public void remove(int index) {
        rangeCheck(index);// i 0 1 2 3 4
        for (int i = index; i < size - 1; i++) {
            elementData[i] = elementData[i + 1]; // i 0 1 3 4 4
        }
        // System.arraycopy(elementData,index+1, elementData, index,
        // size-(index+1));//index从0开始
        elementData[--size] = null;// 最后一个元素是elementData[size-1] =null 同时
                                    // size减一,此时size=4
    }

    public void remove(Object obj) {
        for (int i = 0; i < size; i++) {
            if (obj.equals(elementData[i])) {
                System.arraycopy(elementData, i + 1, elementData, i, size
                        - (i + 1));
                elementData[--size] = null;
            }
        }
    }

    public void insert(Object obj, int index) {
        rangeCheck(index);
        if (false == sizeCheck()) {
            increaseCapacity();
        }
        for (int i = index; i < size; i++) {// 0 1 2 3 4
            elementData[i + 1] = elementData[i];
        }
        elementData[index] = obj;
    }

    private void rangeCheck(int index) {
        if (index >= size) { // index从0开始 比size小 size本来就大于零;
            try {
                throw new Exception();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        MyArrayList list = new MyArrayList(2);
        list.add(123);
        list.add(45);
        list.add(12133);
        list.remove(2);
        System.out.println(list.get(1));
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值