ArrayList源码学习

本文深入解析了ArrayList的工作原理,包括其内部实现细节如数组扩容机制、基本操作如add/remove/get等方法的具体实现,以及如何安全地进行遍历操作。

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

本质:数组
两个成员(属性), elementDatasize
1.new
new的时候给 elementData赋值了一个空数组
  private static final Object[] EMPTY_ELEMENTDATA = {};
    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
     * DEFAULT_CAPACITY when the first element is added.
     */
    private transient Object[] elementData ;
    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size ;
    /**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param   initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public ArrayList( int initialCapacity ) {
        super ();
        if ( initialCapacity < 0)
            throw new IllegalArgumentException( "Illegal Capacity: " +
                                               initialCapacity );
        this . elementData = new Object[ initialCapacity ];
    }
    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        super ();
        this . elementData = EMPTY_ELEMENTDATA ;
    }

如果new的时候给了一个长度,但是并不会立马体现在size上
如下,只是new了一个这样长度的数组
  public ArrayList( int initialCapacity ) {
        super ();
        if ( initialCapacity < 0)
            throw new IllegalArgumentException( "Illegal Capacity: " +
                                               initialCapacity );
        this . elementData = new Object[ initialCapacity ];
}


2.size()
很尴尬,返回了private的size属性
public int size() {
        return size ;
    }


3.add()
  public boolean add(E e ) {
        ensureCapacityInternal( size + 1);  // Increments modCount!!增加mod数,我猜是增加操作的次数,记录下操作了多少次
        //并且其中如果数组长度太小,则增加数组长度
        elementData [ size ++] = e ;
        return true ;
    }


4.add(index,element)
public void add ( int index , E element ) {
        rangeCheckForAdd( index );  //判断index是否正确,不正确抛异常
        ensureCapacityInternal( size + 1);  // Increments modCount!!
        System. arraycopy ( elementData , index , elementData , index + 1,
                         size - index );
        elementData [ index ] = element ;
        size ++;
    }

5.remove(index)
  public E remove ( int index ) {
        rangeCheck( index );
        modCount ++;
        E oldValue = elementData( index );
        int numMoved = size - index - 1;
        if ( numMoved > 0)
            System. arraycopy ( elementData , index +1, elementData , index ,
                             numMoved );
        elementData [-- size ] = null ; // clear to let GC do its work
        return oldValue ;
    }
public boolean remove (Object o ) {
        if ( o == null ) {
            for ( int index = 0; index < size ; index ++)
                if ( elementData [ index ] == null ) {
                    fastRemove( index );
                    return true ;
                }
        } else {
            for ( int index = 0; index < size ; index ++)
                if ( o .equals( elementData [ index ])) {
                    fastRemove( index );
                    return true ;
                }
        }
        return false ;
    }

    private void fastRemove( int index ) {
        modCount ++;
        int numMoved = size - index - 1;
        if ( numMoved > 0)
            System. arraycopy ( elementData , index +1, elementData , index ,
                             numMoved );
        elementData [-- size ] = null ; // clear to let GC do its work
    }

6.get/set
    @SuppressWarnings ( "unchecked" )
    E elementData( int index ) {
        return (E) elementData [ index ];
    }

    public E get( int index ) {
        rangeCheck( index );
        return elementData( index );
    }

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


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

    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 int lastIndexOf(Object o ) {
        if ( o == null ) {
            for ( int i = size -1; i >= 0; i --)
                if ( elementData [ i ]== null )
                    return i ;
        } else {
            for ( int i = size -1; i >= 0; i --)
                if ( o .equals( elementData [ i ]))
                    return i ;
        }
        return -1;
    }



总结
    1). ArrayList实际上是通过一个数组去保存数据的,当我们构造ArrayList时,如果使用默认构造函数,ArrayList的默认容量大小是10。
    2). 当ArrayList容量不足以容纳全部元素时,ArrayList会自动扩张容量,新的容量 = 原始容量 + 原始容量 / 2。
int newCapacity = oldCapacity + ( oldCapacity >> 1);(1.7可能与1.6版本不太一样)
    3). ArrayList的克隆函数,即是将全部元素克隆到一个数组中。
    4). ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写出“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。
   5). 在做ArrayList的遍历的时候有3中遍历的方法,分别是随机访问遍历,用迭代器遍历和强制for循环遍历,按照效率来说最快的是随机访问遍历,最差的是迭代器遍历。
    6). ArrayList的遍历是不安全的,在遍历的时候如果改变了集合的结构会抛出ConcurrentModificationException异常。也就是快速失败机制(fail-fast机制),在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时或者当遍历操作的数量大大超过可变操作的数量时,可以用CopyOnWriteArrayList来替代ArrayList。CopyOnWriteArrayList核心机制是任何对array在结构上有所改变的操作(add、remove、clear等),CopyOnWriterArrayList都会copy现有的数据,再在copy的数据上修改, 这样就不会影响COWIterator中的数据了,修改完成之后改变原有数据的引用即可。同时这样造成的代价就是产生大量的对象,同时数组的copy也是相当有损耗的。


在遍历过程中,不能删除!!!
超级for中会报错,普通for循环中,会遍历不到你删除的元素下个元素


1. 用户与权限管理模块 角色管理: 学生:查看实验室信息、预约设备、提交耗材申请、参与安全考核 教师:管理课题组预约、审批学生耗材申请、查看本课题组使用记录 管理员:设备全生命周期管理、审核预约、耗材采购与分发、安全检查 用户操作: 登录认证:统一身份认证(对接学号 / 工号系统,模拟实现),支持密码重置 信息管理:学生 / 教师维护个人信息(联系方式、所属院系),管理员管理所有用户 权限控制:不同角色仅可见对应功能(如学生不可删除设备信息) 2. 实验室与设备管理模块 实验室信息管理: 基础信息:实验室编号、名称、位置、容纳人数、开放时间、负责人 功能分类:按学科(计算机实验室 / 电子实验室 / 化学实验室)标记,关联可开展实验类型 状态展示:实时显示当前使用人数、设备运行状态(正常 / 故障) 设备管理: 设备档案:名称、型号、规格、购置日期、单价、生产厂家、存放位置、责任人 全生命周期管理: 入库登记:管理员录入新设备信息,生成唯一资产编号 维护记录:记录维修、校准、保养信息(时间、内容、执行人) 报废处理:登记报废原因、时间,更新设备状态为 "已报废" 设备查询:支持按名称、型号、状态多条件检索,显示设备当前可用情况 3. 预约与使用模块 预约管理: 预约规则:学生可预约未来 7 天内的设备 / 实验室,单次最长 4 小时(可设置) 预约流程:选择实验室→选择设备→选择时间段→提交申请(需填写实验目的) 审核机制:普通实验自动通过,高危实验(如化学实验)需教师审核 使用记录: 签到 / 签退:到达实验室后扫码签到,离开时签退,系统自动记录实际使用时长 使用登记:填写实验内容、设备运行情况(正常 / 异常),异常情况需详细描述 违规管理:迟到 15 分钟自动取消预约,多次违规限制预约权限 4. 耗材与安全管理模块 耗材管理: 耗材档案:名称、规格、数量、存放位置、
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值