Java之ArrayList实现

 

目录

一.前言:

二.ArrayList实现:

    2.1思路分析:

      2.1.1  add()方法:

      2.1.2  数组动态扩容: 

      2.1.3 set()方法: 

      2.1.4   contain()方法:

      2.1.5  remove()方法 :


一.前言:

Arraylist和Linkedlist都是继承自List接口,方法都基本相同——功能相同。但是他们的实现方式却不同。所以对于相同的操作,两者的效率可能也会不同。

扫描二维码关注公众号,回复: 15643776 查看本文章

数据结构中的线性表有两种表现形式,一种按顺序存储的顺序表,一种链式存储的链表。而Arraylist就是以数组为基础,顺序表存储实现的。

LinkedList是是以链表为基础实现的。

这篇博客只是简单的实现Arraylist的增删改查功能,没有写构造方法和其他的属性和方法。如有需要改进的,还请指正。

二.ArrayList实现:

    2.1思路分析:

1.Arraylist是以数组实现的,所以我们首先可以定义一个长度为10,类型为object的数组作为属性。

         Object array[]=new Object[10];

         2.1.1  add()方法:

add方法的作用是添加元素到集合,也就是把元素对象添加到数组中,这个怎么操作呢?

     List集合是有索引确定位置的,我们每次完成一次赋值,那么数组的索引值加一。增加一个成员变量count用来计数增加的元素个数,同时也可以算作索引值。

 代码:

@Override
    public boolean add(Object o) {
        grow();
        System.out.println("扩容之后的长度"+array.length);
        array[count]=o;
        count++;
        return true;
    }

 

注意点:

add方法是有两个的,这个是重载另一个add方法:

作用是:把元素插入确定的索引位置。

 插入到对应位置之后,那么后面的值就要对应的往后移,来个插入的元素腾出位置。用代码怎么表示这个后移的过程呢?

       先看图:

   从图中分析,插入位置后面的元素数组都要往后移,这个时候为了避免后移过程中,后面一个元素赋值给后后面元素,以此往后,把元素值给覆盖掉,我们从最后面开始后移。开始值为count(元素个数),当移到插入位置时结束,每一次移动减一。 

 代码:

 @Override
    public void add(int index, Object element) {
    grow();
        System.out.println("扩容之后的长度"+array.length);
        for(int i=count;i>index;i--){
            array[i+1]=array[i];
        }
        array[index]=element;
    }

       2.1.2  数组动态扩容: 

这个只是我们基本数组的赋值操作,没有涉及到集合的核心——动态数组扩容机制。

   动态数组扩容分析:

 元素个数超过了数组长度时,我们这个时候就需要把数组长度扩大。所以首先判断元素个数是否大于数组长度,当大于时,创建一个新的数组,新的数组长度可以自己定义(最后是老数组的2倍),有了一个新的数组,可以把老的数组元素用for循环放到新数组中。最后也是最关键的一步,把老数组名(地址值)指向新数组名(地址值),我们用的时候还是老数组,但是老数组实际已经变成新数组了。

     代码:

 /*
    数组的动态扩容
    1.当我的数组添加的长度大于数组的定义的长度时,扩容
    2.定义一个新数组,把新数组的长度增加为老数组长度的两倍
    3.for循环将数组中的元素赋值到新数组中
    4.把老数组的地址指向新数组
     */
    public void grow(){
    if(count>array.length){
        //新数组的长度增加为老数组长度的两倍
        Object[] newarray = new Object[array.length*2];
        //数组中的元素赋值到新数组中
        for(int i=0;i<array.length;i++){
            newarray[i]=array[i];
        }
        //老数组的地址指向新数组
        newarray=array;
    }
    }

2.1.3 set()方法: 

set()方法作用:给定要修改值的索引,以及对象。只需要通过索引值,然后把对象赋值给该索引值位置,把原来的元素对象覆盖掉,最后返回对应位置的元素。

 代码:

/*
修改
 */
    @Override
    public Object set(int index, Object element) {
        array[index]=element;
        return array[index];
    }

    2.1.4   contain()方法:

contain()方法作用:查找集合中有没有这个元素。可以遍历整个数组,使用equals方法,比较是否有相同的数组。

 注意:

遍历的时候,遍历长度不能是数组长度,这样报NullPointerException错误,只能是遍历数组中元素个数(count变量)

代码:

  /*
    查找
     */
    @Override
    public boolean contains(Object o) {
        //定义一个标记
        boolean flag=false;
        for (int i = 0; i <count ; i++) {
            //当找到就返回true,否则返回false.
            if(array[i].equals(o)){
                flag=true;
            }else{
                flag=false;
            }
        }
        return flag;
    }

     2.1.5  remove()方法 :

Arraylist支持两种删除方式:

  1.按照下标删除

  2.按照对象删除

先分析第一种,传入要删除的元素的下标,先通过索引值找到该元素,记录该元素,因为我们按照下标删除方法是返回删除元素。这时候直接调用System类中arraycopf方法,直接把该下标后面所有的元素往前移,也就是直接把后面的所有元素赋值到索引位置。

   arraycopf方法:

将数组中指定的数据拷贝到另一个数组中。也可以直接拷贝到本数组中。

         System.arraycopf方法中参数含义:

参数序号 参数名称 参数类型 参数含义
1 src Object 源数组
2 srcPos int 源数组索引起始位置
3 dest Object 目标数组
4 destPos int 目标数组索引起始位置
5 length int 复制元素个数

代码

 /*
    删除
     */
    @Override
    public boolean remove(Object o) {
        //定义一个标记
        boolean flag=false;
        for (int i = 0; i <count ; i++) {
            if(array[i].equals(o)){
                remove(i);
                flag=true;
            }
        }
        return flag;
    }

    @Override
    public Object remove(int index){
        //删除指定位置的对象
        Object oldvaule=array[index];
        //求出目标数组的索引的位置
        int num = count - index - 1;
        //把index之后的元素全部赋值到nummoved位置
        if (num > 0){
            System.arraycopy(array, index+1, array, index,
                    num);
        }
        array[--count] = null; 
        return oldvaule;
    }

猜你喜欢

转载自blog.csdn.net/qq_50692350/article/details/126251036