Java模拟实现ArrayList(数据结构)

一、ArrayList的构造

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、ArrayList常见操作

在这里插入图片描述

三、模拟实现

1.创建类及其构造方法

public class MyArrayList1<E> {
    private Object[] array;
    private int size;

    //构造方法:无参构造
    public MyArrayList1(){

    }
    public int size(){
        return  size;
    }
}

由于列表中存放元素各种类型都有可能,这里采用泛型<E>。

2.指定顺序表初始容量

public MyArrayList1(int initCapacity){
    if(initCapacity>=0){
         array=new Object[initCapacity];
    }else{
         throw new IllegalArgumentException("初始容量为负数");
    }
}

初始容量必须为正整数,否则抛异常。

3.判断列表是否为空

public boolean isEmpty(){
        return size==0;
    }

4.尾插

    public boolean add(E e){
        ensureCapacity(size+1);
        array[size++]=e;
        return true;
    }
    //扩容
    private static final int MAX_ARRAY_SIZE=Integer.MAX_VALUE-8;
    private void ensureCapacity(int initCapacity){
        int oldCapacity= array.length;
        //初步预计按照1.5倍大小扩容
        int newCapacity=oldCapacity+(oldCapacity>>1);
        //如果扩容后小于初始容量,则仍然按照初始容量
        if(newCapacity<initCapacity){
            newCapacity=initCapacity;
        }
        //如果扩容后超过最大容量,则按照最大容量
        if(newCapacity>MAX_ARRAY_SIZE){
            newCapacity=MAX_ARRAY_SIZE;
        }
        array= Arrays.copyOf(array,newCapacity);
    }

步骤:
1.扩容
2.将元素放在size的位置
3.将size+1
细化扩容:
1.首先设置列表的最大值:
数组对象的形状和结构(如int值数组)与标准Java对象类似。主要区别在于数组对象有一个额外的元数据,用于表示数组的大小。所以这里的最大值是整型最大值-8.
2.初步预计按照1.5倍大小扩容,如果扩容后小于初始容量,则仍然按照初始容量;如果扩容后超过最大容量,则按照最大容量。
3.使用copyOf进行扩容

5.将e插入到index位置

    public void add(int index,E e){
        rangeCheckForAdd(index);
        ensureCapacity(size+1);

        //将index及其之后的元素统一往后搬移一个位置
        for(int i=size-1;i>=index;i--){
            array[i+1]=array[i];
        }
        array[index]=e;
        size++;
    }
    //检测插入时下标是否异常
    private void rangeCheckForAdd(int index){
        if(index>size){
            throw new IllegalArgumentException("add下标越界");
        }
    }

步骤:
1.检测插入时下标是否异常,是的话抛出异常
2.扩容
3.将index及其之后的元素统一往后搬移一个位置(这里一定要注意从后往前搬,如果从前往后搬会出现搬移的所有元素都是同一个元素的现象)

6.删除index位置上元素

    public E remove(int index){
        rangeCheck(index);

        E e=(E)array[index];
        //将index之后的元素统一往前搬移一个位置
        for(int i=index+1;i<size;i++){
            array[i-1]=array[i];
        }
        size--;
        return e;
    }
    //检测下标是否异常
    private void rangeCheck(int index){
        if(index<0||index>=size){
            throw new IndexOutOfBoundsException("下标越界");
        }
    }

步骤:
1.检测下标是否异常,是的话抛出异常
2.将下标为index的元素强转为E类型,方便后续返回
3.将index之后的元素统一往前搬移一个位置(从前往后)

7.删除遇到的第一个o

    public boolean remove(Object o){
        int index=indexOf(o);
        if(index==-1){
            return false;
        }
        remove(index);
        return true;
    }
    //获取o第一次出现的位置
    private int indexOf(Object o){
        if(o==null){
            for(int i=0;i<size;i++){
                if(array[i]==null){
                    return i;
                }
            }
        }else{
            for(int i=0;i<size;i++){
                if(array[i]==o){
                    return i;
                }
            }
        }
        return -1;
    }

步骤:
1.获取o第一次出现的位置,将null单独处置,如果没有o返回-1,返回false
2.有的话调用remove().返回true

8.获取index位置上元素

    public E get(int index){
        rangeCheck(index);
        E e=(E)array[index];
        return e;
    }

步骤:
1.检测下标是否异常
2.将下标index位置元素强转为E类型并返回

9.将index位置上的元素设置为e

    public E set(int index,E e){
        rangeCheck(index);
        array[index]=e;
        return e;
    }

步骤:
1.检测下标是否异常
2.将index位置元素设置为e
3.返回e

10.清空

    public void clear(){
        for(int i=0;i<size;i++){
            array[i]=null;
        }
        size=0;
    }

将每个元素设置为null,size=0.

11.判断o是否在线性表中

    public boolean contains(Object o){
        return indexOf(o)>0;
    }

其实就是判断o所在下标是否大于o,因为当时indexOf()不在时返回-1.

12.截取部分list

    MyArrayList1<E> subList(int fromIndex,int toIndex){
        if(toIndex-fromIndex<0){
            throw new IllegalArgumentException("参数非法");
        }
        MyArrayList1<E> list=new MyArrayList1<>(toIndex-fromIndex);
        for(int i=fromIndex;i<toIndex;i++){
            list.add((E)array[i]);
        }
        return list;
    }

步骤:
1.判断fromIndex和toIndex参数合法性
2.创建一个新列表用来保存截取后的列表

13.重写toString

    @Override
    public String toString(){
        String s="[";
        if(size>0){
            for(int i=0;i<size-1;i++){
                s+=array[i];
                s+=",";
            }
            s+=array[size-1];
        }
        s+="]";
        return s;
    }

14.主方法

    public static void main(String[] args) {
        MyArrayList1<Integer> list=new MyArrayList1<>(3);
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        System.out.println(list);
        System.out.println("长度为:"+list.size());

        list.add(0,0);
        System.out.println(list);
        if(list.contains(5)){
            list.add(5);
        }

        list.add(0);
        System.out.println(list);
        System.out.println(list.indexOf(0));
        System.out.println(list.lastIndexOf(0));

        list.remove(0);
        System.out.println(list);

        list.clear();
        System.out.println(list);
    }
}

四、输出结果

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dhdhdhdhg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值