jdk源码剖析之ArrayList

本文详细解析了ArrayList的工作原理,包括初始化过程、扩容策略、序列化机制及其适用场景。特别关注ArrayList如何处理数组空间分配,并介绍了它在读多写少场景中的优势。

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

    ArrayList中最重要的是elementData数组和size,主要是通过数组实现。ArrayList中有几点细节需要了解:

1.创建对象时分配的空间。

    ArrayList的构造方法中并没有为elementData数组分配空间,而是在Add方法中判断当前ArrayList是否为空,若为空则分配DEFAULT_CAPACITY(10)的空间。

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    }

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

2.ArrayList数组空间分配的原则,数组大小增长的规律

    ArrayList中grow方法说明了数组大小的分配,当我们数组大小需要扩容的时候是通过扩大到原来的1.5倍来解决,若扩大到1.5倍无法解决问题,则直接扩大到我们需要的minCapacity,最后若minCapacity比我们配置的MAX_ARRAY_SIZE还要大,则扩展到Integer.MAX_VALUE。因此我们可以看出ArrayList支持的最大为Integer.MAX_VALUE,否则就会抛出OutOfMemoryError。

    /**
     * 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.elementData为何定义为transient?

    这是为了序列化是不序列化elementData,由于在elementData中有许多分配的空的空间,若进行序列化会造成空间的浪费。在序列化与反序列化过程中会调用writeObject和readObject方法,只会存有有效的信息。

    /**
     * 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();
        }
    }

    /**
     * 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
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not 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();
            }
        }
    }

4.ArrayList的应用场景

    其应用场景其实就是数组的应用场景,适用于读多写少的场景,因为对于数组的读相对简单,依赖索引的读,其时间复杂度为O(1),但是数组依赖索引的写时间复杂度为O(n)。

基于C2000 DSP的电力电子、电机驱动和数字滤波器的仿真模型构建及其C代码实现方法。首先,在MATLAB/Simulink环境中创建电力电子系统的仿真模型,如三相逆变器,重点讨论了PWM生成模块中死区时间的设置及其对输出波形的影响。接着,深入探讨了C2000 DSP内部各关键模块(如ADC、DAC、PWM定时器)的具体配置步骤,特别是EPWM模块采用上下计数模式以确保对称波形的生成。此外,还讲解了数字滤波器的设计流程,从MATLAB中的参数设定到最终转换为适用于嵌入式系统的高效C代码。文中强调了硬件在环(HIL)和支持快速原型设计(RCP)的重要性,并分享了一些实际项目中常见的陷阱及解决方案,如PCB布局不当导致的ADC采样异常等问题。最后,针对中断服务程序(ISR)提出了优化建议,避免因ISR执行时间过长而引起的系统不稳定现象。 适合人群:从事电力电子、电机控制系统开发的技术人员,尤其是那些希望深入了解C2000 DSP应用细节的研发工程师。 使用场景及目标:①掌握利用MATLAB/Simulink进行电力电子设备仿真的技巧;②学会正确配置C2000 DSP的各项外设资源;③能够独立完成从理论设计到实际产品落地全过程中的各个环节,包括但不限于数字滤波器设计、PWM信号生成、ADC采样同步等。 其他说明:文中提供了大量实用的代码片段和技术提示,帮助读者更好地理解和实践相关知识点。同时,也提到了一些常见错误案例,有助于开发者规避潜在风险。
RA4M2开发IOT(10)----集成LPS22DF气压计 优快云文字教程:https://coremaker.blog.youkuaiyun.com/article/details/148830559 B站教学视频:https://www.bilibili.com/video/BV1DjNmzyEuV 概述 本篇文章将延续现有 “动态显示 MEMS 数据” 的框架,在同一条 I²C 总线上新增 LPS22DF 数字气压计。 项目将具备 惯性 + 气压 的完整环境感知能力,并且借助涂鸦平台可快速把本地大气数据同步到云端,为室内气候监测、爬山/无人机高度预警等场景奠定基础。 硬件准备 首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。 主控为R7FA4M2AD3CFL#AA0 产品特性 LPS22DF是一款超紧凑型压阻绝对压力传感器,可用作数字输出气压计。LPS22DF相比前代产品具有更低的功耗和更小的压力噪声。 该器件包含传感元件和IC接口,该接口通过I²C、MIPI I3CSM或SPI接口实现传感元件与应用的通信,同时该器件也支持用于数据接口的广泛Vdd IO。检测绝对压力的传感元件由悬浮膜组成,采用ST开发的专门工艺进行制造。 LPS22DF采用全压塑孔LGA封装(HLGA)。可保证在-40 °C到+85 °C的温度范围都能工作。封装上有开孔,以便外部压力到达传感元件。 260-1260 hPa 的绝对压力范围,适用于多种气压应用。 最低电流消耗可达 1.7 μA,适合低功耗设备。 压力精度达 0.2 hPa,并具备 0.34 Pa 的低噪声和 0.45 Pa/°C 的温度补偿偏移。 通信模式 对于LPS22DF,可以使用IIC进行通讯。 最小系统图如下所示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

morning_judger

您的鼓励是我创作最大的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值