当前位置: 首页 > news >正文

Vector底层结构和源码分析(JDK1.8)

参考视频:韩顺平Java集合

image.png

  • Vector 类的定义说明:
    image.png
  • Vector 的底层也是一个对象数组,protected Object[] elementData;
  • Vector 是线程同步的,即线程安全,Vectoe 类的操作方法带有 synchronized 关键字:
    public synchronized boolean add(E var1) {  
        ++this.modCount;  
        this.ensureCapacityHelper(this.elementCount + 1);  
        this.elementData[this.elementCount++] = var1;  
        return true;  
    }
    
  • 在开发中,需要线程同步安全时,考虑使用 Vector。

源码示例

未指定初始容量

  • 测试源码
    • 观察调用空参构造器,创建 Vector 的实例的细节(第一次扩容)
    • 观察第一次添加元素(不扩容)
    • 观察第十一次添加元素(第二次扩容)
    	@Test  
    	public void test1(){  
    	    List list = new Vector();  
    	  
    	    for (int i = 1; i <= 20; i++) {  
    	        list.add(i);  
    	    }
        }
    

空参创建 Vector(初次扩容)

  • 调用空参构造器:实际上在该构造器中调用了有参构造器,并传入参数10。

    image.png
  • capacityIncrement 参数用于指定每次扩容时的容量增量‌。当Vector的容量不足以容纳新添加的元素时,它会根据 capacityIncrement 的值来增加容量。如果 capacityIncrement 大于0,则之后每次扩容的容量为当前的容量加上capacityIncrement;如果 capacityIncrement 小于或等于0,则每次扩容的容量为当前容量的一倍。image.png
  • 也就是创建了一个长度为 10 的数组。(此时elementData.length=10

第一次添加元素(不扩容)

  • 调用 add() 方法添加元素“1”到 Vector 集合中:
  • 数组修改次数+1,ensureCapacityHelper() 确认当前数组是否有所需要的容量大小(elementCount+1=1);如果没有则进行扩容,否则不动。
  • (注意:在 Vector 中使用变量 elementCount 记录元素个数,而不是 size)image.png
  • ensureCapacityHelper() 判断当前数组容量(elementData.length)是否满足所需容量 (var1) image.png
  • 此时 elementData.length=10,满足所需容量 var1=1 的需求,所以不扩容。
  • 回到原方法:在 elementCount 处存储要添加的元素 var1。并且 elementCount+1。
    image.png

第 11 次添加元素(第二次扩容)

  • 添加元素“11”到 Vector 数组中。
    image.png
  • 此时数组容量(elementData.length=10)已经不满足所需容量==(var1=11)==了,所以需要扩容,进入 grow() 方法中
    image.png|475
  • var2=当前数组长度==(此时elementData.length=10)==
  • var3=要扩容的目标长度(如果 capacityIncrement >0,则扩容为原始长度+ capacityIncrement;若=0,则扩容为原始长度的两倍)
  • 此时 capacityIncrement 没有值,所以 var3=10+10=20
  • 判断目标扩容的长度是否超过数组的范围。
  • Arrays.copyOf() 作用:创建一个 var 3 容量大小的数组(20),并将原数组中的元素拷贝至新数组,赋值给 elementData。
    image.png
  • 至此,就完成了数组的扩容。
  • 回到 add 方法的主逻辑中:在 elementCount 处存储要添加的元素 var1。并且 elementCount+1。
    image.png

指定初始容量

  • 测试源码
    • 观察调有参构造器,创建 Vector 的实例的细节(第一次扩容)
    • 观察第一次添加元素(不扩容)
    • 观察第九次添加元素(第二次扩容)
    	@Test  
    	public void test1(){  
    	    List list = new Vector(8);  
    	  
    	    for (int i = 1; i <= 20; i++) {  
    	        list.add(i);  
    	    }
        }
    

调用有参构造器,指定初始容量(第一次扩容)

  • 调用有参构造器,其内部调用了构造器,并为 capacityIncrement 赋值为 0。
    image.png
  • 那么此时构造器创建了一个长度为 8 的数组。==(elementData.length=8) ==image.png

第一次添加数据(不扩容)

  • 记录修改数组的次数+1
  • 确认当前数组是否含有 elementCount+1=1 个大小的容量。如果没有则扩容。
    image.png
  • 检查当前数组的容量==(element.length=8)是否满足所需容量的大小(var1=1)==。
    image.png
  • 显然,此时容量是够的,不需要扩容,跳过 grow()
  • 回到 add() 的主逻辑中:在 elementCount 处存储要添加的元素 var1。并且 elementCount+1=1
    image.png

第九次添加数据(第二次扩容)

  • 此时需要的容量 (elementCount+1=9),进入 ensureCapacityHelper() 中。
    image.png
  • 判断当前数组长度 (elementData.length=8) 是否满足所需容量长度==(var1=9)==
    image.png
  • 显然,不够。所以需要扩容,进入 grow()
  • var2=原始数组容量(8)
  • var3=需要扩容到的目标容量长度,此时 capacityIncrement=0,所以扩容至原始长度的两倍(16)
  • 检查目标长度 var3是否满足需求 var1
  • 检查目标长度是否超过数组范围上限。
  • Arrays.copyOf() 作用:创建一个 var3 容量大小的数组(16),并将原数组中的元素拷贝至新数组,赋值给 elementData。
    image.png
  • 至此,数组的扩容完成。回到 add() 主逻辑:在 elementCount 处存储要添加的元素 var1。并且 elementCount+1=9
    image.png

相关文章:

  • 【不动产登记全解析】范围、内容与不予登记的情形
  • 思维链医疗编程方法论框架(Discuss V1版)
  • MySQL 8 设置允许远程连接(Windows环境)
  • Oracle 查询数据库对象的DDL语句
  • 解锁 AI 开发的无限可能:邀请您加入 coze-sharp 开源项目
  • antd的Form表单校验的方式有几种
  • 网络空间安全(29)漏洞扫描
  • undefined和null的区别 (新手小白级教程)
  • 第5关:猴子爬山
  • 航空动力系统适航标准要点手册
  • OpenRewrite配方之import语句的顺序——org.openrewrite.java.OrderImports
  • transformer bert 多头自注意力
  • element-plus中Autocomplete自动补全输入框组件的使用
  • 【Spring】详细剖析Spring程序
  • 多线程实现批量保存数据
  • PE,ELF,COFF
  • 基于物联网设计的疫苗冷链物流监测系统
  • 【前端知识】前端构建工具webpack的平替vite
  • 【软件测试】--面试
  • 如何用终端运行一个SpringBoot项目
  • 做好公司网站/网站seo
  • html5 经典网站/公司查询
  • 做网站编辑大专可以吗/sem代运营
  • 网站建设公司营业执照经营范围/关键词推广seo
  • 动态网站建设 教学大纲/长沙seo运营
  • 淘宝网站的建设目标是/十大网站平台