自己试着编写ArrayList,更有助于对ArrayList的理解

本文深入解析ArrayList的底层实现,包括其构造方法、add方法、扩容机制等核心功能。详细介绍了ArrayList在不同JDK版本下的初始容量及扩容策略,以及如何通过自定义构造函数指定初始容量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ArrayList的底层无非就是其众多的使用方法及很重要的扩容机制:
封装的方法有:add\get\set\indexOf\remove\size
扩容机制:
jdk1.7之前初始默认为10,
jdk1.8之后初始默认为0,实际值长度大于0小于10时,扩容为10;实际长度大于10时,则扩容大小为实际长度+实际长度右移2的一次方(实际长度/2

package com.yjkf.zh.arrayList;

import java.io.Serializable;

/**
 * 包含构造1函数(有参,无参)、add()、扩容机制
 */
public class MyArrayList implements Serializable { 

    //使用这个字段,来判断当前集合是否被并发修改,即迭代器并发修改的fail-fast机制
    private transient int modCount = 0;

    //第一次扩容的容量
    private static final int DEFAULT_CAPACITY = 10;

    //用于初始化空的List
    private static  final Object[] EMPTY_ELEMENT_DATA = {};

    //实际存储的元素,transient代表不能被序列化
    transient Object[] elementData;

    //实际List集合大小,可以从0开始
    private int size;

    //无参构造
    public MyArrayList(){
        this.elementData = EMPTY_ELEMENT_DATA;
    }

    //有参构造
    public MyArrayList(int initislCapcity){
        if(initislCapcity>0){
            this.elementData = new Object[initislCapcity];
        }else if(initislCapcity == 0){
            this.elementData = EMPTY_ELEMENT_DATA;
        }else{
            throw new IllegalArgumentException("参数异常");
        }
    }

    public boolean add(Object e){
        //判断容量
        ensureCapacityInternal(size+1);

        //使用下标赋值,尾部插入
        elementData[size++] = e;
        return true;

    }

    //计算容量+确保容量
    private void ensureCapacityInternal(int minCapacity){
        //用于并发判断
        modCount++;
        //如果是初次扩容,则使用默认的容量
        if(elementData == EMPTY_ELEMENT_DATA){
            minCapacity = Math.max(DEFAULT_CAPACITY,minCapacity);
        }

        //是否需要扩容,需要的最少容量大于现在数组的长度则要扩容
        if(minCapacity - elementData.length >0){
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity + (oldCapacity>>1);
            //如果新容量<最小容量,则将最新的容量到给新的容量
            if(newCapacity - minCapacity <0){
                newCapacity = minCapacity;
            }
            //创建新数组
            Object[] objects = new Object[newCapacity];

            //将旧的数据复制到新的数组里面
            System.arraycopy(elementData,0,objects,0,elementData.length);
            //修改引用
            elementData = objects;
        }
    }

    /**
     * 通过下标获取对象
     * @param index
     * @return
     */
    public Object get(int index){
        rangeCheck(index);
        return elementData[index];
    }
    private void  rangeCheck(int index){
        if(index>size || size<0){
            throw new IndexOutOfBoundsException("数据越界了");
        }
    }

    /**
     * 判断对象所在的位置
     * @return
     */
    public int indexOf(Object o){
        if(o==null){
            for(int i =0;i<size;i++){
                if(elementData[i]==null){
                    return i;
                }
            }
        }else {
            for (int i=0;i<size;i++){
                if(o.equals(elementData[i])){
                    return i;
                }
            }
        }
        return -1;
    }

    public Object set(int index,Object obj){
        rangeCheck(index);
        Object oldValue = elementData[index];
        elementData[index] = obj;
        return oldValue;
    }

    /**
     * 根据索引删除元素
     * @param index
     * @return
     */
    public Object remove(int index){
        rangeCheck(index);
        //用于并发判断
        modCount++;
        Object oldValue = elementData[index];
        //计算要删除的位置后面有几个元素
        int numMoved = size - index -1;
        if(numMoved>0){//拷贝哪一个,从哪里开始,拷贝到哪去,从哪里开始,拷贝多少个
            System.arraycopy(elementData,index+1,elementData,index,numMoved);
        }
        //将多出的位置置为空,没有引用对象,垃圾收集器可以回收,如果不为空,将会保存一个引用,可能会造成内存泄漏
        elementData[--size]=null;
        return oldValue;
    }

    //获取数组实际大小
    public int size(){
        return this.size;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值