ArrayList 源码

0、transient
  • 被它修饰的元素不会被序列化
    使用另外的序列化方式,节省了空间(ArrayList的容量>=实际元素数量,如果直接序列化ArrayList的elementData[]元素数组,会把不含元素的空间也序列化,造成空间的浪费)
  • 这是一个用于存储ArrayList元素的缓冲数组,ArrayList的容量是数组的长度。
    任意一个空的,使用无参构造方法创建出来的ArrayList,第一次添加元素的时候,都要被扩充到默认初始化容量
    在这里插入图片描述
  • 序列化
    把ArraList实例以流的形式保存
 /**
     * Save the state of the <tt>ArrayList</tt> instance to a stream (that
     * is, serialize it).
     *
     * @serialData The length of the array backing the <tt>ArrayList</tt>
     *             instance is emitted (int), followed by all of its elements
     *             (each an <tt>Object</tt>) in the proper order.
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // Write out element count, and any hidden stuff
        // 写出元素计数和其他隐式的属性,序列化期间被修改就会抛出异常
        int expectedModCount = modCount;
        s.defaultWriteObject();

        // Write out size as capacity for behavioural compatibility with clone()
        // 将实际元素个数,作为用于克隆的可信的容量
        s.writeInt(size);

        // Write out all elements in the proper order.
        // 依次写入元素
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }
        // 多线程修改数据,抛出异常
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

   
  • 反序列化
    从流里读出数据,重组ArrayList
 /**
     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
     * deserialize it).
     */
     // 从流里读
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // 数组置空
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        // 读入元素个数和其他隐藏属性
        s.defaultReadObject();

        // Read in capacity
        // 读入容量 ignore 说明这一步没啥用
        s.readInt(); // ignored
       // 就像克隆一样,给数组分配空间,依据实际元素值而不是容量大小
        if (size > 0) {
            // be like clone(), allocate array based upon size not capacity
            // 计算容量
            int capacity = calculateCapacity(elementData, size);
            SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
            //判断扩容
            ensureCapacityInternal(size);
           // 读取元素
            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }
1、 变量含义
  • int DEFAULT_CAPACITY 默认初始化容量 10
  • Object[] EMPTY_ELEMENTDATA 空数组
    构造方法带初始容量,但是初始容量为0
    在这里插入图片描述
    构造方法带集合参数,但是集合为空
    在这里插入图片描述
  • Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA 空数组
    只用于无参构造
    在这里插入图片描述
  • Object[] elementData 真正存储元素的位置
    (无参,创建的是空数组;有参,但是容量为0,创建的也是空数组,两个空数组只是变量名字不同,用于区分不同的构造情况,然后在第一次新增元素的时候采用不同的扩容方式)
    ArrayList arrayList = new ArrayList(); 对于这个 size是0,第一次add的时候,才变为10
 /**
     * 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 == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; 
  • int size 当前list内 含有的元素个数,注意和 容器容量区分开
    private static final int DEFAULT_CAPACITY = 10;
    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};
    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
   
2、在末尾新增元素以及扩容

先确保容量够用,再赋元素

     /**
     * Appends the specified element to the end of this list.
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

   private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

  • 先计算需要的最小容量 (也就是添加成功之后,实际元素个数)
    传入参数 minCapacity = size+1
    返回值 = 无参且第一次新增?max(minCapacity,default_Capicaty):minCapacity
   private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

  • modCount++(多线程操作,抛出异常),并判断 所需容量和数组实际长度的关系,来决定是否扩容
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
  • 数组空间不够 ——> 扩容
    • newCapacity = oldCapacity+oldCapacity/2, 也就是1.5倍,然后进行边界判断:如果新容量还是不够用,直接使用minCapacity;如果新容量超过max_size,使用最大容量
    • 然后用新容量 拷贝数组(副本),然后赋给elementData
    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
3、在指定位置添加/删除元素

数组的两种复制方式 Arrays/System

  • Arrays.copyOfRange(源数组,起点,终点后一个位置)
    在这里插入图片描述
    在这里插入图片描述
    Arrays.copyof (源数组,复制长度) 基于System.arraycopy()
    新建了一个数组副本,最后返回副本
    在这里插入图片描述在这里插入图片描述
    复制长度超过源数组,默认值来凑(int --0 String–null)
    在这里插入图片描述
  • System.arraycopy(源数组,源数组起始位置,目标数组,目标数组起始位置,复制长度)
    目标数组必须已经存在–可以是自己 原地修改
    在这里插入图片描述
    在这里插入图片描述

正文

  • 先判断要添加元素的位置 是不是合规
    在这里插入图片描述
  • 再判断是否需要扩容
  • 然后进行数组复制
 public void add(int index, E element) {
        rangeCheckForAdd(index);
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

  • 删除也差不多 走流程 然后原地复制 最后返回被删除的元素(如果是boolean,删除成功返回true,失败返回false)
    在这里插入图片描述
4、其他方法
  • get 直接调用数组获取元素的方法 O(1)
    在这里插入图片描述在这里插入图片描述
  • toArray 返回的是副本
    在这里插入图片描述
  • 清空 遍历 赋予null O(n)
    在这里插入图片描述
  • indexOf 遍历,比值 O(n)
    在这里插入图片描述
    在这里插入图片描述
【博士论文复现】【阻抗建模、验证扫频法】光伏并网逆变器扫频与稳定性分析(包含锁相环电流环)(Simulink仿真实现)内容概要:本文档围绕“博士论文复现”主题,重点介绍了光伏并网逆变器的阻抗建模与扫频法稳定性分析,涵盖锁相环和电流环的Simulink仿真实现。文档旨在通过完整的仿真资源和代码帮助科研人员复现相关技术细节,提升对新能源并网系统动态特性和稳定机制的理解。此外,文档还提供了大量其他科研方向的复现资源,包括微电网优化、机器学习、路径规划、信号处理、电力系统分析等,配套MATLAB/Simulink代码与模型,服务于多领域科研需求。; 适合人群:具备一定电力电子、自动控制或新能源背景的研究生、博士生及科研人员,熟悉MATLAB/Simulink环境,有志于复现高水平论文成果并开展创新研究。; 使用场景及目标:①复现光伏并网逆变器的阻抗建模与扫频分析过程,掌握其稳定性判据与仿真方法;②借鉴提供的丰富案例资源,支撑博士论文或期刊论文的仿真实验部分;③结合团队提供的算法与模型,快速搭建实验平台,提升科研效率。; 阅读建议:建议按文档目录顺序浏览,优先下载并运行配套仿真文件,结合理论学习与代码调试加深理解;重点关注锁相环与电流环的建模细节,同时可拓展学习其他复现案例以拓宽研究视野。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值