ArrayList源码浅析

STM32F407VET6与CH395Q串口通信实战:从零搭建以太网客户端(附完整代码) 本文详细介绍了基于STM32F407VET6微控制器与南京沁恒微CH395Q以太网芯片,通过串口通信从零搭建TCP客户端应用的完整实战过程。内容涵盖硬件连接、驱动层设计、基于FreeRTOS的任务实现以及核心调试技巧,并提供了完整的代码示例,帮助嵌入式开发者快速实现设备联网功能。 阅读详情

特性:

1、ArrayList是List接口的可变数组的实现
2、实现了所有可选列表操作,并允许包括null在内的所有元素
3、除了实现List接口外,此类还提供了一些方法来操作内部用来存储列表的数组的大小
4、每个ArrayList都有一个容量,该容量是指用来存储列表元素的数组的大小
5、它总是至少等于列表的大小
6、随着向ArrayList中不断添加元素,其容量也自动增加
7、自动增长会带来数据向新数组的重新拷贝,因此,如果可预知数据量的多少,可在构造ArrayList时指定其容量
8、实现了Serializable接口,因此支持序列化,能够通过序列化传输
9、实现了RandomAccess接口,支持快速随机访问,
10、实现了Cloneable接口,能被克隆

tips:ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个函数安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。

源码分析:

(1)底层使用数组

transient Object[] elementData; // non-private to simplify nested class access

transient:是java的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进去的。

(2)构造方法

Java提供了3个构造函数
 //构造一个指定初始容量的空列表
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}
//共享的空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//构造一个默认初始容量为10的空列表
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

//构造一个包含指定Collection的元素的列表,这些元按照Collection的迭代器返回他们的顺序排列的
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

(3)存储数据

总共提供了5中存储数据的方法:

第一种:更换

/**
* 使用给定的值替换特定位置的值
*
* @param index 需要替换的位置
* @param element 替换的值
* @return 该位置的之前的值
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
    rangeCheck(index); //检测index是否在数组大小范围内

    E oldValue = elementData(index);//返回数组index位置的值
    elementData[index] = element; //将index位置的值赋值为传入的值
    return oldValue;
}

//检测index是否在数组范围内,如果不在就抛出异常
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

//返回index位置elementData数组的值
E elementData(int index) {
    return (E) elementData[index];
}

第二种:添加元素

//添加元素到数组的最后位置
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //如果初始化为空        
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //就设置数组大小为10
    }
    ensureExplicitCapacity(minCapacity);
}

默认初始化大小
private static final int DEFAULT_CAPACITY = 10;

private void ensureExplicitCapacity(int minCapacity) {
    modCount++; //数组被修改的次数

    // overflow-conscious code
    if (minCapacity - elementData.length > 0) //如果最小需求长度大于目前数组的大小
        grow(minCapacity); //增加数组的大小
}

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length; //获取之前数组的长度
    int newCapacity = oldCapacity + (oldCapacity >> 1); //获取新的数组的长度=1.5*旧的数组长度
    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); //数组的复制
}

//获取最大数组长度
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError(); 
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;  //如果最小需求长度大于最大范围,就返回Integer的最大值;否则返回最大范围
}

第三种:元素插入到指定位置

/**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
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++;
}

第四种:添加集合

public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray(); //将集合转换成数组
    int numNew = a.length; //新的集合的长度
    ensureCapacityInternal(size + numNew);  // Increments modCount
    System.arraycopy(a, 0, elementData, size, numNew); 
    size += numNew;
    return numNew != 0;
}

第五种:添加集合到指定位置

public boolean addAll(int index, Collection<? extends E> c) {
    rangeCheckForAdd(index);

    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount

    int numMoved = size - index; //移动的位置
    if (numMoved > 0)
        System.arraycopy(elementData, index, elementData, index + numNew,
                         numMoved); //将插入的位置以及其后的元素后移

    System.arraycopy(a, 0, elementData, index, numNew);
    size += numNew;
    return numNew != 0;
}

(4)读取数据

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

    return elementData(index);
}

(5)删除

第一种:删除指定位置的元素

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++) //遍历查找是否有位置的值为null
            if (elementData[index] == null) {
                fastRemove(index); //快速删除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); //将index后面的元素全部前移一位,覆盖index位置的值
    elementData[--size] = null; // clear to let GC do its work
}

第三种:删除一个集合中的所有元素

public boolean removeAll(Collection<?> c) {
    Objects.requireNonNull(c); //Object中的方法,用于判断元素非空
    return batchRemove(c, false);
}

private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData; //将原有的数组赋值给新的数组
    int r = 0, w = 0;
    boolean modified = false;
    try {
        //功能是将未出现在集合c中的元素放到数组的前端,从第一个开始放
        for (; r < size; r++)
            if (c.contains(elementData[r]) == complement) //查找集合c的是否包含数组中的元素
                elementData[w++] = elementData[r];//不包含,就将r位置的元素放到数组的前部位置
    } finally {
        // Preserve behavioral compatibility with AbstractCollection,
        // even if c.contains() throws.
        if (r != size) {
            System.arraycopy(elementData, r,
                             elementData, w,
                             size - r); //复制数组
            w += size - r;
        }
        if (w != size) {
            // clear to let GC do its work 
            for (int i = w; i < size; i++) //设置后面的元素为null,方便GC回收
                elementData[i] = null;
            modCount += size - w; //记录修改次数
            size = w;
            modified = true;
        }
    }
    return modified;
}
/*
*  将src数组的srcPos位置的元素复制到dest数组的destPos位置,复制长度为length,
* 使用的是JNI,调用c的方法,这样可以加快速度
* @param      src      the source array.
* @param      srcPos   starting position in the source array.
* @param      dest     the destination array.
* @param      destPos  starting position in the destination data.
* @param      length   the number of array elements to be copied.
* @exception  IndexOutOfBoundsException  if copying would cause
*               access of data outside array bounds.
* @exception  ArrayStoreException  if an element in the <code>src</code>
*               array could not be stored into the <code>dest</code> array
*               because of a type mismatch.
* @exception  NullPointerException if either <code>src</code> or
*               <code>dest</code> is <code>null</code>.
*/
public static native void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);
【机器学习】Anaconda安装后打不开jupyter notebook(网页不自动跳出) anaconda安装成功以后,jupyter notebook可以出现打开的路径,能够手动复制粘贴地址路径打开,却不能自动跳转到网页。解决的办法是在配置文件中加入指定的浏览器配置信息。 阅读详情

相关推荐

LTX-2.3 V1.6:8G显存本地AI视频生成工具与int8量化加速实践

这次我们来看一个本地部署的AI视频生成工具——LTX-2.3文字图片生成带音频视频工具V1.6版本。这个工具最大的特点是支持int8量化加速,相比原版提速2-4倍,效果更好,而且8G显存就能运行,不需要搭建复杂环境,解压即可使用。 对于想要在本地电脑上快速生成带音频视频内容的用户来说,这个工具解决了几个关键痛点:首先是硬件门槛低,8G显存意味着大多数主流游戏显卡都能胜任;其次是部署简单,避免了Python环境配置、依赖包冲突等常见问题;最后是性能优化明显,int8加速让生成速度大幅提升。 本文会重点演示如何

hqmln的博客 1233

ArrayList源码之添加方法详解

ArrayList底层是动态数组,最重要的就是这个grow方法,首先给一个数值作为数组范围,然后在数组原来的基础上增大一半的范围,如果这个增大的数小于增大一半的范围,那就是增大一般的范围,就是至少增大一半,第一次添加元素直接扩大至10,最大为Integer.MAX_VALUE-8,(防止频繁复制数组),然后复制数组,然后在存储元素最后一位的后一位赋值增加的值。 在指定索引出添加,...

alexdedream的博客 494

在Ubuntu22.04.2远程服务器上搭建OHIF+Orthanc

在Ubuntu远程服务器上不翻墙,但是本地windows需要科学上网开始之前,首先在终端输入export -p查看是否有代理端口如下如果有就关了,输入如下命令。

weixin_51116549的博客 1332

ArrayList源码

1、ArrayList介绍 ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。 1)ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修...

大龙的博客 783

VS Code配置Java开发环境避坑指南:从JDK到Spring Boot插件全流程

本文详细介绍了在VS Code中配置Java开发环境的完整流程,涵盖JDK选择、环境变量配置、核心插件安装、构建工具优化及Spring Boot项目专项设置。特别针对常见问题提供避坑方案,帮助开发者快速搭建高效稳定的开发环境,提升Java和Spring Boot开发效率。

weixin_28839699的博客 976

基于 ESP32 的智能药盒提醒装置设计与实现

本装置基于 ESP32 实现了智能药盒的核心功能,硬件选型兼顾成本与实用性,软件设计模块化、易拓展。后续可通过 ESP32 的 WiFi 模块接入物联网平台(如阿里云、OneNet),实现远程设置提醒、服药状态反馈等功能,进一步提升智能化水平。该装置能有效解决老人忘服药问题,具有较高的实用价值与推广潜力。

weixin_42300449的博客 1043

ArrayList、LinkedList、Vector区别总结与源码浅析

ArrayList、LinkedList、Vector 区别总结与源码浅析 写在前面,本文为笔者学习整理总结,因此,若有任何不严谨或错误之处,还望不吝指教! 本文内容: 一、区别总结 二、源码浅析 1. ArrayList 2. LinkedList 3. Vector 一、区别总结 ArrayList,底层采用数组构建,因此决定了擅随机访问,弱...

大爷没钱 402

Plant Simulation与ABB机器人虚实结合

Plant Simulation与ABB机器人虚实结合

santayana的专栏 1869

ArrayList 源码浅析

ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。ArrayList实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现。除该类未实现同步外,其余跟Vector大致相同。每个ArrayList都有一个容量(capacity),表示底层数组的实际大小,容器内存储元素的个数不能多于当前容量。当向容器中添加元素时,如果容量不足,容器会自动增大底层数组的大小。...

一枚爪洼同鞋 272

在 ABAP Cloud 里优雅读取与解析 XML:用 sXML Reader 把接口数据落成结构化 ABAP

ABAP Cloud中XML解析实践 摘要:本文介绍了在ABAP Cloud环境下解析XML数据的最佳实践。针对企业系统中常见的XML格式数据,文章推荐使用sXML库中的CL_SXML_STRING_READER进行流式解析,而非传统的DOM方式。重点解析了命名空间(Namespace)、属性(Attribute)和CDATA等关键概念的处理方法,并比较了两种读取属性的策略:通扫所有属性(NEXT_ATTRIBUTE)和精准取值(GET_ATTRIBUTE_VALUE)。文章提供了完整的ABAP Cloud

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 185

利用baostock获取上市公司财务指标

利用baostock获取上市公司的财务指标 1、导入模块,登录baostock import baostock as bs import pandas as pd import time # 登陆系统 lg = bs.login() # 显示登陆返回信息 print('login respond error_code:'+lg.error_code) print('login respond error_msg:'+lg.error_msg) 2、查询股票代码、行业板块 # 查询股票代码 rs=.

firefox_yau的博客 2097

ArrayList集合源码浅析

ArrayList集合源码浅析ArrayList简介主要成员变量构造函数1、无参构造函数2、带有参数为初始容量initialCapacity的构造函数3、带有参数为Collection集合的构造函数主要操作方法add方法(添加单个元素)add方法(批量添加,在指定位置添加)remove方法get方法总结 ArrayList简介 ArrayList 是 Java 集合框架中比较常用的数据结构了。ArrayList是可以动态增长和缩减的索引序列,内部封装了一个动态再分配的Object[]数组 这里我们可以看到

Delimma_A的博客 321

从 VS Code 登录 ABAP Destination,一次把前后端连接跑通

最近很多 ABAP 开发者开始把 VS Code 纳入日常开发环境,原因很直接,VS Code 的轻量体验、命令面板、文件树、插件生态和 AI 编程能力,已经深深影响了现代开发者的工作方式。SAP 官方发布的 ABAP Development Tools for VS Code,也把 ABAP Cloud 开发模型带进了这个编辑器里。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 220

ArrayList实现原理及源码浅析

ArrayList的实现原理 ArrayList底层是用一个数组实现的。 Object[] elementData; 当elementData装满元素时,会通过扩容的方式来增加elementData的容量 浅析ArrayList源码 添加元素 添加元素最常用的是boolean add(E e)方法,它实际上调用的是将元素插入的指定位置的方法void add(int index, E element)。 所以我们只需要搞懂void add(int index, E element)就可以了 public

qq_28015441的博客 230

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

java-ArrayList源码简单浅析

ArrayList源码简单浅析 ArrayList 应该是开发中用的最多的集合对象了,ArrayList是可以动态增长和缩减的索引序列,它是基于数组实现的List类。 一些定义 public class ArrayList&lt;E&gt; extends AbstractList&lt;E&gt; implements List&lt;E&gt;, RandomAccess, C...

小城我家 243

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Java的ArrayList源码浅析

public class ArrayList extends AbstractList implements Cloneable, Serializable, RandomAccess Java在集合模块中提供的一个工具类,继承AbstractList抽象类,支持泛型。 本日志分析的源码来自android-22\java\util\ArrayList.java 该类包含3个域

TikiWiky的专栏 539

JDK源码剖析之ArrayList浅析

ArrayList概述         下文用昵称“小A”表示ArrayList的一个实例:)         ArrayList是一个实现了List接口的大小可变的数组,可类比于Vector,但是ArrayList是unsynchronized(非同步的),而Vector类是synchronized(同步的)。获取ArrayList信息的一些方法比如size()、isEmpty()、get(

梵高先生的专栏 346

java abstractnumlist_ArrayList源码浅析

ArrayList源码浅析概述ArrayList是底层结构为数组,长度可变的有序集合位置java.util.ArrayList类定义继承AbstractList实现List、RandomAccess、Cloneable、SerializableAbstractListListRandomAccessCloneableSerializable1.AbstractList_作用:简单实现List中的方...

weixin_36318306的博客 229

ArrayList源码个人浅析

1.构造器 A.无参构造 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//空 } B.有参构造 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Ob...

xiaoweige的博客 172
上一篇: HashMap源码浅析
下一篇: java 断点续传
明天的增加
博客等级 码龄11年 22粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值