java集合篇(一)——ArrayList扩容原理

2023-05-16

    相信大家都对ArrayList相当熟悉了,今天笔者就对ArrayList的源码进行解读,讲解一下对ArrayList扩容的基本原理。

虽然大家都有用过,但还是简单介绍一下吧,ArrayList实现了List的接口,并且实现了序列化,同样具有collection的方法,add,remove等,时间复杂度都是O(1),对于n个数据则为O(n)。好了,接下来具体看下ArrayList的源码(笔者使用的是jdk1.8版本):

/**
     * 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; // non-private to simplify nested class access  
/**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    此处我们可以看到,我们的数据其实是放在ArrayList<E>引用的一个Object数组,也就是elementData数组,我们来看看它的add方法:

/**
     * 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 == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    从add传进来的元素开始,在ensure方法中进行了size的判断,首先判断取最小容量,然后对最小容量和目前数据所需容量最比对,如果最小容量并不满足,则需要增加大小:

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

      这里新的容量是将就旧的加上后移一位的,也就是二进制位右移,然后进行判断,如果新增的比最小容量要小,则赋值为最小容量,如果超过了最大值,则赋值int的最大值,也就是2^31-1,十六进制数为0x7fffffff,然后调用Arrays的copyof方法去将原来数组的值复制过去。

    这里可以做一个测试demo,由于属性是非公有的,所以使用了反射的方法去获取(关于反射的使用可以参考笔者的另一篇文章):

    

public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<String>();
		TestIntValue value = new TestIntValue();
			list.add("ss");
		int actualLength = value.getActualLength(list);
		int size = list.size();
		System.out.println("list此时的容量为:" + actualLength);
		System.out.println("list此时的大小为:" + size);
	}
	
	/**
	 * 反射获取elementData容量大小
	 * @param mList
	 * @return
	 */
	public int getActualLength(ArrayList<String> mList){
		Class<?> mClass = mList.getClass();
		Field f = null;
		int length = 0;
		try {
			f = mClass.getDeclaredField("elementData");
			f.setAccessible(true);
			Object[] o = (Object[])f.get(mList);
			length = o.length;
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
		return length;
	}

此时只是增加了一个值,所以此时的大小为1,容量大小为10:


如果我们给他塞入超出10的值呢:


此时容量大小已经变成15了,可见,大小的确是10 + 5来的,所以,他的扩容是大概增加了1.5倍的大小。

以上就是扩容的过程了,谢谢大家~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java集合篇(一)——ArrayList扩容原理 的相关文章

  • 如何编写 Maven 构建脚本来执行 Java

    如何在构建过程中或构建刚刚完成后执行 Java 程序 可以直接从 pom 中执行此操作吗 mvn exec java Dexec mainClass org sonatype mavenbook weather Main EDIT 假设我想
  • 将 WAR 部署到 Tomcat(Spring Boot + Angular)

    我正在尝试使用以下命令部署 Spring Boot 应用程序WAR包装至Tomcat 10 应用程序已成功部署 但是 当我尝试访问端点时 它会导致404 未找到 战争文件 应用程序 war http localhost 8080 appli
  • 在Java Servlet中获取通过jquery ajax发送的参数[重复]

    这个问题在这里已经有答案了 我在网上搜索这个主题 但找不到有效的示例 我会很高兴有人能给我帮助 这就是我测试的 ajax url GetJson type POST dataType json contentType application
  • 在java代码中创建postgresql表

    我有一个与 postgreSQL 数据库连接的 java 代码 现在 我希望当它连接到数据库时 我还将创建数据库表 但我的问题是 它不会创建数据库 我不知道问题是什么 这是我的代码 Statement st null ResultSet r
  • Java:为什么.class文件中的方法类型包含返回类型,而不仅仅是签名?

    class 文件的常量池中有一个 NameAndType 结构 它用于动态绑定 该类可以 导出 的所有方法都被描述为 签名 返回类型 喜欢 getVector Ljava util Vector 当某些 jar 中方法的返回类型发生更改时
  • JAX-WS 入门 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有人可以推荐一些关于 JAX WS 入门的好教程吗 使用各种工具 如 wsgen 等 您可以从这里开始 通过 Java SE 6 平台介绍
  • Jenkins 未显示 Maven 编译器错误

    在 Jenkins 中构建多模块 maven 3 项目时 如果出现构建错误 我们会收到一条神秘消息 表明 Maven 编译器插件失败 这在上周才刚刚开始发生 INFO BUILD FAILURE INFO INFO Total time 1
  • 当前平台不支持桌面 API

    我遇到过这个错误 java lang UnsupportedOperationException 当前平台不支持桌面 API 我将从我的 java 应用程序中打开一个文件 我用这个方法 Desktop getDesktop open new
  • Google 表格使用 API 密钥而不是 client_secret.json

    In the QuickStart java示例Java 快速入门 https developers google com sheets api quickstart java他们使用OAuth client ID识别该应用程序 这会弹出一
  • 是否可以使用 Apache Tika 提取表信息?

    我正在寻找 pdf 和 MS Office 文档格式的解析器 以从文件中提取表格信息 当我看到 Apache Tika 时 正在考虑编写单独的实现 我能够从任何这些文件格式中提取全文 但我的要求是提取表格数据 我希望有 2 列采用键值格式
  • java:为什么主线程等待子线程完成

    我有一个简单的java程序 主线程 main 创建并启动另一个线程t class T extends Thread Override public void run while true System out println Inside
  • 在 Eclipse 中删除空块之前的新行

    我更喜欢奥尔曼式 http en wikipedia org wiki Brace style Allman style大括号 例如 if foo magical prancing unicorn stuff 而不是 if foo unma
  • JFrame 在连续运行代码时冻结

    我在使用时遇到问题JFrame 它会冻结 连续运行代码 下面是我的代码 点击时btnRun 我调用了该函数MainLoop ActionListener btnRun Click new ActionListener Override pu
  • Spring Security 角色层次结构不适用于 Thymeleaf sec:authorize

    我正在使用 Spring Security 3 2 5 RELEASE 和 ThymeLeaf 2 1 4 RELEASE 我已经在安全上下文中定义了角色层次结构 在我的视图层中我正在使用sec authorize属性来定义菜单项 我希望看
  • 获取接收者的设备令牌以在 Firebase 中发送通知

    所以我正在学习如何使用 firebase 发送设备到设备的通知 我看到了这个answer https stackoverflow com a 42548586 5237289发送通知 看起来很简单 现在 我知道要获取发件人的令牌 它应该如下
  • 在 Eclipse RCP 应用程序中禁用插件贡献

    我经常遇到这个问题 但尚未找到解决方案 每当我编写一个新的基于 Eclipse RCP 的应用程序并包含来自 Eclipse 平台的插件时 我都会 继承 其中一些插件的 UI 贡献 大多数贡献 菜单项 键盘快捷键 属性页 都很有用 但有时我
  • 如何在 JASPIC 中保存经过身份验证的用户?

    我开发了一个安全认证模块 SAM 并实现了validateRequest方法 我还有一个简单的 Web 应用程序配置为使用此 SAM In my validateRequest方法 我检查 clientSubject 并设置一个Caller
  • 在 Spring MVC 中将请求写入文件

    我希望能够将整个请求写入 Spring MVC 控制器中的文件 我已尝试以下操作 但即使我使用大量参数发出 POST 请求 文件也始终为空 RequestMapping method RequestMethod POST value pay
  • 难以理解 通配符

    我有一个非常基本的问题 下面的代码无法编译 假设 Apple Extends Fruit List
  • 如何在不使用 -cp 开关的情况下在 Groovy 中自动加载数据库 jar?

    我想简化调用 Oracle 数据库的 Groovy 脚本的执行 如何将 ojdbc jar 添加到默认类路径以便我可以运行 groovy RunScript groovy 代替 groovy cp ojdbc5 jar RunScript

随机推荐

  • 过两小时后,自动更新mysql中的字段

    现在的项目中有一个需求 xff0c 就是扫码支付的二维码有效期只有两个小时 xff0c 两个小时后二维码就会失效 xff0c 想要记录这个失效的状态 xff0c 就要用mysql中的定时器来自动更新字段 创建存储过程 span class
  • 微信扫码支付

    微信扫码支付用的是apiv3接口 xff0c 点击查看微信扫码支付官方文档 编写微信支付封装实体类 span class token comment 微信平台证书VO 64 author shenlu 64 date 2020 12 21
  • MongoDB查询时根据对象中的对象的属性进行判断

    接受同事留下来的项目 xff0c 没想到运行的时候还有bug xff0c 无法对对象的对象的属性进行条件查询 xff0c 非常操蛋 xff0c 琢磨了一下午终于解决了 话不多说 xff0c 贴代码 span class token anno
  • 解决Nacos服务注册使用Docker容器内网ip问题

    一 问题 使用docker部署的jar启动时注册到nacos上的ip会使用docker的内网ip跟端口作为注册地址 xff1a 这样会导致使用gateway路由转发时报错 xff1a span class token class name
  • Dubbo3.0 整合 Nacos

    首先呢 xff0c 这个项目分为provider提供者和consumer消费者 xff0c 使用的版本是dubbo3 0 7 xff0c nacos是2 0 4 xff08 注意 xff1a 要使用dubbo3 xff0c nacos的版本
  • Kafka动态启用消费者

    1 设置监听器禁止自启动 span class token class name KafkaListenerContainerFactory span span class token generics span class token p
  • Gazebo 学习笔记之构建一个Robot 1:模型目录的结构和要求

    文章目录 概述1 模型数据库存储库2 模型数据库的结构2 1 插件目录2 2 Meshes 目录2 3 Material 目录2 4 数据库配置 Database Config2 5 模型配置 Model Config2 6 模型 SDF2
  • 已解决:Android Studio 报错No IDEA annotations attached to the JDK 1.8, some issues will not be found

    今天把sdk删了 xff0c 重装 xff0c 然后打开AS后发现 No IDEA annotations attached to the JDK 1 8 some issues will not be found 的警告 项目无法运行 x
  • Android Studio配置模拟器AVD移动至其他盘

    平时我们在Android Studio中使用的模拟器 xff0c 这些模拟器会在C盘中创建模拟器镜像文件 在C Users UsersName android中 xff0c avd文件夹就是用来存放模拟器镜像文件的 xff0c 为了节省c盘
  • Python3 虚拟环境激活

    如果你正在使用Python3 xff0c 虚拟环境已经成为内置模块 xff0c 可以直接通过如下命令来创建它 xff1a python3 m venv venv 注 xff1a 这个命令不一定能够执行成功 xff0c 比如译者在Ubuntu
  • 培训机构众多,如何选择优秀嵌入式培训机构?

    为什么说选择一个优秀的 专业的嵌入式培训学校很重要 xff1f 选择优秀的嵌入式培训学校 xff0c 学习嵌入式技术 xff0c 您将可能找到一份好工作 xff0c 得到10倍 xff0c 甚至100倍价值回报 xff1b 从此你将有独立生
  • 接口防重方案设计

    幂等性原理 xff1a 前台的多次请求 xff0c 对于后台 xff0c 也是同一次请求 xff1b 通常接口设计方式 xff1a 1 前端的页面提交按钮置灰 xff0c 防止用户重复点击 xff1b 2 对前端提交的token进行校验 x
  • 微信小程序-轮播图实现

    好久不见 xff0c 今天小h来分享一下如何实现一个微信小程序的轮播图实现方式 xff1a 前提条件是具有微信开发者工具 xff0c 还有对应的开发者ID xff0c 这些基础条件我这边就直接跳过了哈 xff0c 直接进入正题 xff1a
  • 所以,到底什么是微服务?

    1 微服务是一种软件架构 xff0c 是聚焦在单一的职责和业务功能 xff0c 具有独立的进程 xff0c 能够单独运行的服务 xff0c 并且与外部服务是通过HTTP进行交互通信的服务 2 微服务比较常见的特性是 xff0c 具有单一职责
  • 关于云服务Bmob的使用方法(上)——上传数据

    关于第三方云服务平台Bmob是怎样使用的 xff1f 我们从两个方面来写 xff0c 一个是传输数据 xff0c 一个是传输文件 第一个是关于bmob传输数据的 xff0c 首先我们在官网http www bmob cn 上面注册我们自己的
  • 关于云服务Bmob的使用方法(下)——上传文件

    上一篇我们说了如何传输数据 xff0c 那么这一篇我们进阶一下 xff0c 来谈谈如何传输文件 xff0c 比如图片 关于如何在bmob上注册和申请 xff0c 上一篇已经有说明 xff0c 不懂的读者可以去看看 xff0c 然后我们直接进
  • 使用栈模拟递归的算法

    这一篇笔者要讲的是如何用栈来模拟递归 xff0c 或者说替代递归的算法 xff0c 现在我们假如要算从三角形数的叠加 xff0c 比如输入10 xff0c 输出是55 xff0c 输入是100 xff0c 输出是5050 xff0c 等等
  • 使用 catkin 的方式创建自定义的 ros 消息

    文章目录 1 写在前面2 创建自定义消息2 1 创建 ros 包2 2 创建 msg 文件2 3 修改 package xml 文件2 4 修改 CMakeLists txt 文件 3 生成 msg 代码文件 1 写在前面 消息文件是描述R
  • "我"与AI

    有人说过 xff0c 在这世界上 xff0c 一共有10种人 xff0c 一种是懂二进制的 xff0c 一种是不懂的 其实 xff0c 在不远的未来 xff0c 这个世界多了两种机器 xff0c 懂AI的 xff0c 以及不懂的 在如今的互
  • java集合篇(一)——ArrayList扩容原理

    相信大家都对ArrayList相当熟悉了 xff0c 今天笔者就对ArrayList的源码进行解读 xff0c 讲解一下对ArrayList扩容的基本原理 虽然大家都有用过 xff0c 但还是简单介绍一下吧 xff0c ArrayList实