一步步深入Java底层原理(三)

为什么桥式传感器(Bridge Sensor)需要用到仪表放大器? 仪表放大器在桥式传感器的应用里起到关键作用,本文介绍桥式传感器的原理、特性,以及信号调理过程,并附上了一个 TINA - TI 的仿真电路。 阅读详情

ArrayList的实现原理:




1. ArrayList概述:



  ArrayList是List接口的可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。
   每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向ArrayList中不断添加元素,其容量也自动增长。自动增长会带来数据向新数组的重新拷贝,因此,如果可预知数据量的多少,可在构造ArrayList时指定其容量。在添加大量元素前,应用程序也可以使用ensureCapacity操作来增加ArrayList实例的容量,这可以减少递增式再分配的数量。 
   注意,此实现不是同步的。如果多个线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。



 

2. ArrayList的实现:

   对于ArrayList而言,它实现List接口、底层使用数组保存所有元素。其操作基本上是对数组的操作。下面我们来分析ArrayList的源代码:




   1) 底层使用数组实现:



Java代码  收藏代码
  1. private transient Object[] elementData;  

    2) 构造方法: 
   ArrayList提供了三种方式的构造器,可以构造一个默认初始容量为10的空列表、构造一个指定初始容量的空列表以及构造一个包含指定collection的元素的列表,这些元素按照该collection的迭代器返回它们的顺序排列的。

Java代码


public ArrayList() {  
    this(10);  
}  
  
public ArrayList(int initialCapacity) {  
    super();  
    if (initialCapacity < 0)  
        throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);  
    this.elementData = new Object[initialCapacity];  
}  
  
public ArrayList(Collection<? extends E> c) {  
    elementData = c.toArray();  
    size = elementData.length;  
    // c.toArray might (incorrectly) not return Object[] (see 6260652)  
    if (elementData.getClass() != Object[].class)  
        elementData = Arrays.copyOf(elementData, size, Object[].class);  
}  




  3) 存储: 
   ArrayList提供了set(int index, E element)、add(E e)、add(int index, E element)、addAll(Collection<? extends E> c)、addAll(int index, Collection<? extends E> c)这些添加元素的方法。下面我们一一讲解:

// 用指定的元素替代此列表中指定位置上的元素,并返回以前位于该位置上的元素。  
public E set(int index, E element) {  
    RangeCheck(index);  
  
    E oldValue = (E) elementData[index];  
    elementData[index] = element;  
    return oldValue;  
}  
// 将指定的元素添加到此列表的尾部。  
public boolean add(E e) {  
    ensureCapacity(size + 1);   
    elementData[size++] = e;  
    return true;  
}  

// 将指定的元素插入此列表中的指定位置。  
// 如果当前位置有元素,则向右移动当前位于该位置的元素以及所有后续元素(将其索引加1)。  
public void add(int index, E element) {  
    if (index > size || index < 0)  
        throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);  
    // 如果数组长度不足,将进行扩容。  
    ensureCapacity(size+1);  // Increments modCount!!  
    // 将 elementData中从Index位置开始、长度为size-index的元素,  
    // 拷贝到从下标为index+1位置开始的新的elementData数组中。  
    // 即将当前位于该位置的元素以及所有后续元素右移一个位置。  
    System.arraycopy(elementData, index, elementData, index + 1, size - index);  
    elementData[index] = element;  
    size++;  
}  



// 按照指定collection的迭代器所返回的元素顺序,将该collection中的所有元素添加到此列表的尾部。  
public boolean addAll(Collection<? extends E> c) {  
    Object[] a = c.toArray();  
    int numNew = a.length;  
    ensureCapacity(size + numNew);  // Increments modCount  
    System.arraycopy(a, 0, elementData, size, numNew);  
    size += numNew;  
    return numNew != 0;  
}  



// 从指定的位置开始,将指定collection中的所有元素插入到此列表中。  
public boolean addAll(int index, Collection<? extends E> c) {  
    if (index > size || index < 0)  
        throw new IndexOutOfBoundsException(  
            "Index: " + index + ", Size: " + size);  
  
    Object[] a = c.toArray();  
    int numNew = a.length;  
    ensureCapacity(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 (E) elementData[index];  
}  


5) 删除:
 ArrayList提供了根据下标或者指定对象两种方式的删除功能。如下:

// 移除此列表中指定位置上的元素。  
public E remove(int index) {  
    RangeCheck(index);  
  
    modCount++;  
    E oldValue = (E) elementData[index];  
  
    int numMoved = size - index - 1;  
    if (numMoved > 0)  
        System.arraycopy(elementData, index+1, elementData, index, numMoved);  
    elementData[--size] = null; // Let gc do its work  
  
    return oldValue;  
}  




// 移除此列表中首次出现的指定元素(如果存在)。这是应为ArrayList中允许存放重复的元素。  
public boolean remove(Object o) {  
    // 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。  
    if (o == null) {  
        for (int index = 0; index < size; index++)  
            if (elementData[index] == null) {  
                // 类似remove(int index),移除列表中指定位置上的元素。  
                fastRemove(index);  
                return true;  
            }  
} else {  
    for (int index = 0; index < size; index++)  
        if (o.equals(elementData[index])) {  
            fastRemove(index);  
            return true;  
        }  
    }  
    return false;  
}  


注意:从数组中移除元素的操作,也会导致被移除的元素以后的所有元素的向左移动一个位置。


Java代码:
public void ensureCapacity(int minCapacity) {  
    modCount++;  
    int oldCapacity = elementData.length;  
    if (minCapacity > oldCapacity) {  
        Object oldData[] = elementData;  
        int newCapacity = (oldCapacity * 3)/2 + 1;  
            if (newCapacity < minCapacity)  
                newCapacity = minCapacity;  
      // minCapacity is usually close to size, so this is a win:  
      elementData = Arrays.copyOf(elementData, newCapacity);  
    }  
}  


从上述代码中可以看出,数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。或者根据实际需求,通过调用ensureCapacity方法来手动增加ArrayList实例的容量。
   ArrayList还给我们提供了将底层数组的容量调整为当前列表保存的实际元素的大小的功能。它可以通过trimToSize方法来实现。代码如下:

public void trimToSize() {  
    modCount++;  
    int oldCapacity = elementData.length;  
    if (size < oldCapacity) {  
        elementData = Arrays.copyOf(elementData, size);  
    }  
}  

 7) Fail-Fast机制: 
ArrayList也采用了快速失败的机制,通过记录modCount参数来实现。在面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。具


该文章转自http://zhangshixi.iteye.com/blog/674856

openclaw通俗入门系列9——流式传输 + 分块 流式传输 = 不等写完就开始发。分块流式传输是把长回复切成几条消息发(所有渠道),草稿流式传输是像打字一样实时显示(仅 Telegram)。可以配置块大小、发送时机、合并规则、类人延迟。 阅读详情

相关推荐

AD9176 双通道高速DAC调试记录

AD9176是一款高性能双通道16位数模转换器,支持高达12.6GSPS采样率,专为多频段无线应用设计。该器件集成8通道15.4Gbps JESD204B接口,支持复数/实数数据输入,每通道最大输入速率达3.08GSPS。关键特性包括:48位高精度NCO、灵活的插值滤波器(最高12倍)、优异的动态性能(SFDR达-83dBc@1.84GHz)以及多芯片同步功能。硬件调试需重点关注时钟配置(建议250M基准时钟)、JESD参数匹配及交流耦合设计。测试指标要求SFDR>55dBc@312MHz,实测值可达65d

universaldata的博客 1492

旷野徒奔-Java底层篇(1.1)

Java底层篇——JVM(1)1、JVM→ JVM 内存结构运行时数据区:堆、方法区、运行时常量池、直接内存、堆和栈区别Java 中的对象一定在堆上分配吗?class文件格式 1、JVM → JVM 内存结构 运行时数据区:堆、方法区、运行时常量池、直接内存、 一、堆 (java Heap) ​ Java 堆(Heap)是 Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。这个内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里

weixin_45386328的博客 937

手把手教你用ADS和CGH40010F模型搭建Doherty功放仿真原型(附工程文件)

本文详细介绍了如何使用ADS软件和CGH40010F GaN器件模型搭建Doherty功放仿真原型,涵盖工程准备、关键电路模块实现、效率优化技巧及常见问题排查。通过实战指南和效率优化技巧,帮助工程师快速掌握Doherty功放设计,提升5G基站和广播发射系统的功率放大器性能。

weixin_26897585的博客 345

JAVA的一些基础点和底层原理总结

HashSet和TreeSet。底层基于TreeMapHashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束;在初始化的时候,会创建一个长度为16的数组,HashMap的扩容是在判断数组的长度是否超过阈值时进行的,这个阈值是数组的长度乘以加载因子(0.75),当超过这个阈值时,会新建一个两倍长度的数组,遍历原数组上的每一个值,并且重新计算它们在新数组上的位置,将原来数组上的元素都存储到新数组对应的位置上。

weixin_55029324的博客 3094

Qt开发中彻底解决中文乱码问题

中文乱码问题主要源于编码不一致需要同时设置控制台和Qt应用程序的编码确保项目文件和环境配置的编码一致文件操作时注意指定正确的编码。

qq_53832058的博客 3405

setoolkit克隆网站获取用户信息

一、环境 kali、DVWA 二、步骤 首先打开kali,输入setoolkit 依次选择选项1-选项2-选项3-选项2 输入钓鱼网站的网址(默认为本地网址) 输入要克隆的网址URL 这里我的网址如图,将网址复制 然后模拟攻击场景,攻击者向受害者发送了一条钓鱼链接,此链接与DVWA的登陆页面完全一样,受害者点击之后并进行登陆信息 点击login之后,用户信息就被setool...

BeatRex的博客 2998

Java底层原理

1.HashSet底层原理: ①HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。 ②它不保证set 的迭代顺序,特别是它不保证该顺序恒久不变。 ③允许使用null元素。 ④是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素。 因此HashSet 的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成。 这里是引用 2.HashMap底层原理: ① HashMap是基于哈希表的Map接口的非同步实现。 ②提供

每天进步一点点,不要逃避 3783

基于深度学习的三维重建算法——详解与实现

随着深度学习技术的迅猛发展,基于深度学习的三维重建算法在最近几年取得了显著的进展。而基于深度学习的三维重建算法通过利用深度神经网络,能够从大规模数据中学习到更准确、鲁棒的三维结构表示。本文综述了基于深度学习的三维重建算法,并给出了相应的源代码。随着深度学习技术的不断发展,我们相信基于深度学习的三维重建算法将会在未来得到更广泛的应用。实验结果表明,基于深度学习的三维重建算法在准确性和鲁棒性方面取得了显著的提升。以上是关于基于深度学习的三维重建算法的详细介绍与实现,希望对您有所帮助。

CyberGenius的博客 1228

Java底层原理基础知识总结(未完)

java和c++的区别 java不提供指针来直接访问内存,程序内存更加安全 Java 的类是单继承的, C++ ⽀持多重继承;虽然 Java 的类不可以多继承,但是接⼝可以多继 承。 Java 有自动内存管理机制,不需要程序员手动释放内存 静态方法和实例方法有何不同 1.在外部调用静态方法时,可以使"类名.方法名",也可以使用"对象名.方法名"。 实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。 2. 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许

Resurrected_Eagle的博客 3090

Python分布式爬虫深度实战:反爬破解+数据清洗+性能优化全流程

分布式爬虫的核心是“调度中心化+执行分布式”,Scrapy-Redis是最易落地的框架,无需从零写调度逻辑;反爬破解要分级应对:基础反爬靠随机UA/限流,进阶反爬靠代理池,高级反爬靠第三方验证码API;数据清洗的关键是“批量处理+标准化”,避免内存溢出,核心字段去重和异常值过滤是必做步骤;性能优化不是单纯加节点,而是从架构(分片)、代码(批量写入)、服务器(索引/网络)三层协同优化,才能实现效率翻倍。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1200

【模型实战】MiMo-VL-7B讲解与实战

维度成绩MMMU70.6(图像理解最难测试之一)VideoMME70.8(视频理解标杆)59.4(超越78B参数模型)56.1(超过专用GUI模型)Elo评分开源VLM排名第一(7B~72B)社区热度过去一个月下载超1,600次(RL+SFT)📌一句话概括MiMo-VL 是目前性能最强、推理最稳、体验最佳、生态最全的7B级开源视觉语言模型。

m0_47867638的博客 1199

JAVA相关的一些底层知识

1.计算机五大核心组成部分 1. 控制器(Control):是整个计算机的中枢神经,其功能是对程序规定的控制信息进行解释,根据其要求进行控制,调度程序、数据、地址,协调计算机各部分工作及内存与外设的访问等。 ​ 2. 运算器(Datapath):运算器的功能是对数据进行各种算术运算和逻辑运算,即对数据进行加工处理。 CPU ​ 3. 存储器(Memory):存储器的功能是存储程序、数据和各种信号、命令等信息,并在需要时提供这些信息。内存 ​ 4. 输入(Input system):输入设备是计算机

weixin_56892092的博客 1192

QCC304x系列开发教程(实战篇)之5.2 QCC3040之提示音

earbud_init.c中,初始化table中UiPrompts_Init /*! \brief Table of initialisation functions */ static const init_table_entry_t appInitTable[] = { ......... {UiPrompts_Init, 0, NULL}, ......... } ui_prompts.c中是提示音音处理的主要逻辑和配置源文件 函数static void uiPro...

心跳包的博客 2395

【JAVA】字符串相关类的底层原理

在所有的编程语言中,字符串是应用最广泛的一种数据类型,它是由一系列字符(如字母、数字、符号)组成的一种数据类型。在Java中,字符串一旦创建就不能修改,每次操作都会产生一个新的字符串。那么这些特性背后的内存原理是怎样的?这就是我今天要分享的主题:字符串在java内存中的底层原理。

2302_79323248的博客 1758

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Java集合的底层原理

Java集合底层原理、哈希表、红黑树

JIU-W的博客 1457

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Java NIO 底层原理

这些机制都允许单线程处理多个I/O操作,避免了传统阻塞I/O的多线程开销。

Made In SQL 1197

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

一步步深入Java底层原理(二)

对于Java来说,一般情况下我们只要知道一些API的用法,一些框架,当然还有最基础的语法就可以进行一定的开发了,但是由于Java虚拟机等一些原因,如果我们不知道其底层原理以及一些东西的实现方法的话,调试改Bug非常困难,所以我们应该有一些Java底层原理的知识。 -------------------------------------------------------------------

StarCoder_WangYue的博客 5653

Java CAS底层原理

Java CAS底层原理 Java CAS底层原理,这一篇就够了!!! CAS全称(Conmpare And Swap)比较并交换,是一种用于在多线程环境下实现同步功能的机制。CAS 操作包含三个操作数 – 内存地址、预期值和新值。CAS 的实现逻辑是将内存地址的数值与预期数值想比较,若相等,则将内存位置处的值替换为新值。若不相等,则不做任何操作。 JAVA中CAS是通过自旋操作完成赋值,若值不相...

Lailai Monkey的博客 6080

Java集合底层原理

Java集合框架的体系结构、集合架构中的类、算法、底层原理

小凯的博客 3062

一步步深入Java底层原理(一)

接触Java也快半年时间了,但是对Java的底层原理还不是非常清楚,最近在看《Java虚拟机(第二版)》,深有启发,顺便把Java知识梳理一下,以便更好的进行接下来的学习。 Java技术体系划分(按照所服务的平台划分): Java Card: 支持一些Java小程序(Applets)运行在小内存设备(如智能卡)上的平台。Java ME(Micro Edition) :支

StarCoder_WangYue的博客 9181

【Java 基础】ConcurrentHashMap 底层原理

ConcurrentHashMap 是线程安全的哈希表,它是 Java 并发包中提供的一种高效的并发 Map 实现。ConcurrentHashMap 底层采用了分段锁的机制,不同的段(Segment)可以被不同的线程同时访问,从而提高了并发性能。

激流丶的博客 5642

java注解的底层原理是什么?

用于描述代码(类、方法、字段、参数等)的。Java 代码在编译后,注解会被存储在。文件,仅用于编译器处理。,不会直接影响代码执行。

2201_75420324的博客 1189

Java 中 String 转 Integer 的方法与底层原理详解

考点解答parseInt和valueOf的区别?一个返回int,一个返回Integer,后者有装箱过程哪个方法更推荐?valueOf推荐用于对象封装,parseInt更轻量用于原始类型有缓存机制吗?✅ 有,范围是为什么 new Integer() 不推荐?每次都会创建新对象,浪费内存,不走缓存池。

m0_73748193的博客 3663

为什么PHP底层不是JAVA?底层原理是什么?

性能:C 语言提供更高的执行效率和更直接的底层操作能力。可移植性:C 语言的高度可移植性和标准库的支持使得 PHP 能够在多种平台上运行。资源管理:C 语言的手动内存管理和系统调用能力对于某些操作非常重要。历史和社区:PHP 的早期设计和社区贡献巩固了 C 语言在 PHP 中的地位。设计哲学:PHP 的简单易用和快速开发特性更适合 Web 开发,而 Java 的健壮性和安全性更适合大型企业级应用。

长风破浪会有时的博客 1206

Java HashMap 集合的底层原理知识点详解

创建新的数组,并将旧数组中的元素重新分配到新数组中:遍历旧数组,对于每个链表或红黑树,根据元素的哈希值和新数组的容量重新计算索引位置,并将元素插入到新数组中。其中,n为数组的长度,hash为键的哈希值。该公式利用了位与(&)运算,当n为 2 的幂次方时,n - 1的二进制形式是全 1,通过位与运算能将哈希值映射到0到n - 1的范围内,从而确定元素在数组中的存储位置。计算元素在数组中的索引位置:根据哈希值计算索引i,如果该位置的数组元素为 null,则直接创建新的节点并插入。二、哈希算法与元素定位​。

2301_81549590的博客 1225

【Java】字符串相关类的底层原理

默认创建一个长度为16的字节数组添加的内容长度小于16,直接存添加的内容大于16会扩容(扩容机制为:原来容量 * 2 + 2)如果扩容之后还不够,以实际长度为准添加的内容长度小于16,直接存// 容量:最多装多少// 长度:已经装了多少// 16// 0// 16// 3添加的内容大于16会扩容(扩容机制为:原来容量 * 2 + 2)// 容量:最多装多少// 长度:已经装了多少// 16// 0// 26 个英文字母// 34// 26。

qq_39921135的博客 1876
上一篇: JSP转译成Servlet详细过程
下一篇: 一步步深入Java底层原理(四)
StarCoder_Yue
博客等级 码龄9年 39粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值