热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ArrayList源码及扩容机制分析

文章目录ArrayList基本特点:类的定义ArrayList类的变量类的构造方法:ArrayList中的常用方法:ArrayList的扩

文章目录

      • ArrayList 基本特点:
      • 类的定义
      • ArrayList类的变量
      • 类的构造方法:
      • ArrayList中的常用方法:
      • ArrayList的扩容机制:
      • ArrayList 的 grow() 扩容方法:
      • ArrayList 的 hugeCapacity(minCapacity) 方法:

ArrayList 位于 java.util 包下

ArrayList 基本特点:

1. 底层动态数组,有序,有下标,可以重复
2. 线程不安全
3. 查询性能较快,增删性能稍差

类的定义

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList实现List接口&#xff0c;继承AbstractList抽象类&#xff0c;另外实现RandomAccess (支持随机访问)、Cloneable(支持拷贝) 两个特殊接口

ArrayList类的变量

// 默认容量大小
private static final int DEFAULT_CAPACITY &#61; 10;
// 空数组
private static final Object[] EMPTY_ELEMENTDATA &#61; {};
// 空数组。&#xff08;用两个的目的是为了知道添加第一个元素时需要创建多大的空间&#xff09;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA&#61;{};
----------
// 真正存储ArrayList中的元素的数组
transient Object[] elementData;
// 存储ArrayList的大小&#xff0c;注意不是elementData的长度
private int size;
-----------
// 数组的最大长度
private static final int MAX_ARRAY_SIZE &#61; Integer.MAX_VALUE - 8;
// 修改次数, 每次add、remove它的值都会加1&#xff08;这个属性是AbstractList中的&#xff09;
protected transient int modCount &#61; 0;

类的构造方法&#xff1a;

// 无参
public ArrayList() {this.elementData &#61; DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

// 带初始长度参数的构造函数
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {// 初始长度参数大于0&#xff0c;用此长度初始化创建元素数组this.elementData &#61; new Object[initialCapacity];} else if (initialCapacity &#61;&#61; 0) {// 初始长度参数为0&#xff0c;使用空数组this.elementData &#61; EMPTY_ELEMENTDATA;} else {//传入参数 <0 抛IllegalArgumentException异常throw new IllegalArgumentException("Illegal Capacity: "&#43;initialCapacity);}
}

// 参数为集合的 构造方法
public ArrayList(Collection<? extends E> c) {// 参数转数组&#xff0c;并赋值给当前集合数组elementData &#61; c.toArray();// 设置元素个数if ((size &#61; elementData.length) !&#61; 0) {// 不是Object数组就转为Object数组if (elementData.getClass() !&#61; Object[].class)elementData &#61; Arrays.copyOf(elementData, size, Object[].class);} else {// 参数中也没有元素时&#xff0c;用空数组替换this.elementData &#61; EMPTY_ELEMENTDATA;}
}

ArrayList中的常用方法&#xff1a;

在这里插入图片描述
这些方法看名字大概就应该知道是干什么的了&#xff0c;不再详细说明。

ArrayList的扩容机制&#xff1a;

先来看一个方法&#xff1a;

private void ensureExplicitCapacity(int minCapacity) {// 修改次数 &#43; 1modCount&#43;&#43;;// 判断是否需要扩容if (minCapacity - elementData.length > 0)grow(minCapacity);
}

这个方法的作用是用来保证ArrayList的容量的。 在ArrayList每次添加操作时&#xff0c;也就是说在每次执行add()、addAll() 方法时&#xff0c;都会调用这个方法&#xff0c;判断数组长度是否需要扩容。如果 添加后需要的长度 > 原来数组的长度&#xff0c;就需要调用grow() 方法进行扩容

ArrayList 的 grow() 扩容方法&#xff1a;

private void grow(int minCapacity) {// 先获取 原数组的长度int oldCapacity &#61; elementData.length;// 右移运算符 原来长度的一半 再加上原长度也就是每次扩容是原来的1.5倍int newCapacity &#61; oldCapacity &#43; (oldCapacity >> 1);if (newCapacity - minCapacity < 0)//如果新的数组容量小于需要的最小容量&#xff0c;即假设新的数组容量是15&#xff0c;最小需要16的容量&#xff0c;则会将16赋予newCapacitynewCapacity &#61; minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)/* * 变量 MAX_ARRAY_SIZE &#61; 2147483639 [0x7ffffff7]* 如果 扩容后的新容量 大于 MAX_ARRAY_SIZE 则会使用hugeCapacity方法*/newCapacity &#61; hugeCapacity(minCapacity);// 确定新数组的容量后&#xff0c;将 原数组数据 copy 到新数组中 去elementData &#61; Arrays.copyOf(elementData, newCapacity);}

通过上面的源码及注释可以看到&#xff0c;ArrayList 扩容长度 一般为原数组长度的1.5倍。如果新数组长度 > 数组规定的最大容量时&#xff0c;会调用 hugeCapacity&#xff08;minCapacity&#xff09; 方法。

ArrayList 的 hugeCapacity(minCapacity) 方法&#xff1a;

// 传入参数为&#xff1a; 添加操作执行后&#xff0c;数组所需要的最小长度
private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // 如果最小长度 <0&#xff0c;抛出 内存溢出 错误throw new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ?// 如果 需要的长度 > 最大数组容量 &#xff0c; 就返回Integer 类型的最大值作为容量Integer.MAX_VALUE :// 否则 就 返回 数组最大容量 作为 新扩容后的 长度。MAX_ARRAY_SIZE;
}

当 grow&#xff08;&#xff09;方法中 计算出的新数组长度 > 数组最大长度 时&#xff0c;调用该方法&#xff0c;判断 操作后元素所需要的长度 是否 &#xff1e; 数组最大长度&#xff0c;如果大于&#xff0c;就返回Integer 类型的最大值 作为新数组长度&#xff0c;否则 仍然返回 数组最大长度 作为新数组长度。


推荐阅读
  • 分享一款基于Java开发的经典贪吃蛇游戏实现
    本文介绍了一款使用Java语言开发的经典贪吃蛇游戏的实现。游戏主要由两个核心类组成:`GameFrame` 和 `GamePanel`。`GameFrame` 类负责设置游戏窗口的标题、关闭按钮以及是否允许调整窗口大小,并初始化数据模型以支持绘制操作。`GamePanel` 类则负责管理游戏中的蛇和苹果的逻辑与渲染,确保游戏的流畅运行和良好的用户体验。 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 本文探讨了 Java 中 Pair 类的历史与现状。虽然 Java 标准库中没有内置的 Pair 类,但社区和第三方库提供了多种实现方式,如 Apache Commons 的 Pair 类和 JavaFX 的 javafx.util.Pair 类。这些实现为需要处理成对数据的开发者提供了便利。此外,文章还讨论了为何标准库未包含 Pair 类的原因,以及在现代 Java 开发中使用 Pair 类的最佳实践。 ... [详细]
  • 本文详细探讨了Java事件处理机制的核心概念与实现原理,内容浅显易懂,适合初学者逐步掌握。通过具体的示例和详细的解释,读者可以深入了解Java事件模型的工作方式及其在实际开发中的应用。 ... [详细]
  • 在前文探讨了Spring如何为特定的bean选择合适的通知器后,本文将进一步深入分析Spring AOP框架中代理对象的生成机制。具体而言,我们将详细解析如何通过代理技术将通知器(Advisor)中包含的通知(Advice)应用到目标bean上,以实现切面编程的核心功能。 ... [详细]
  • 深入解析Java虚拟机的内存分区与管理机制
    Java虚拟机的内存分区与管理机制复杂且精细。其中,某些内存区域在虚拟机启动时即创建并持续存在,而另一些则随用户线程的生命周期动态创建和销毁。例如,每个线程都拥有一个独立的程序计数器,确保线程切换后能够准确恢复到之前的执行位置。这种设计不仅提高了多线程环境下的执行效率,还增强了系统的稳定性和可靠性。 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 链表作为一种与数组并列的基本数据结构,在Java中有着广泛的应用。例如,Java中的`ArrayList`基于数组实现,而`LinkedList`则是基于链表实现。链表在遍历操作时具有独特的性能特点,特别是在插入和删除节点时表现出色。本文将详细介绍单向链表的基本概念、操作方法以及在Java中的具体实现,帮助读者深入理解链表的特性和应用场景。 ... [详细]
  • 开发日志:201521044091 《Java编程基础》第11周学习心得与总结
    开发日志:201521044091 《Java编程基础》第11周学习心得与总结 ... [详细]
  • 在Android开发过程中,序列化是一个重要的概念,尤其是在数据传输和存储时。本文详细解析了Parcelable序列化的原理及其应用场景,并对比了其他序列化方式,如Serializable。通过具体的实例和代码示例,帮助开发者更好地理解和掌握Parcelable的使用方法,避免在实际开发和面试中遇到相关问题。 ... [详细]
  • AIX编程挑战赛:AIX正方形问题的算法解析与Java代码实现
    在昨晚的阅读中,我注意到了CSDN博主西部阿呆-小草屋发表的一篇文章《AIX程序设计大赛——AIX正方形问题》。该文详细阐述了AIX正方形问题的背景,并提供了一种基于Java语言的解决方案。本文将深入解析这一算法的核心思想,并展示具体的Java代码实现,旨在为参赛者和编程爱好者提供有价值的参考。 ... [详细]
  • 本文介绍了UUID(通用唯一标识符)的概念及其在JavaScript中生成Java兼容UUID的代码实现与优化技巧。UUID是一个128位的唯一标识符,广泛应用于分布式系统中以确保唯一性。文章详细探讨了如何利用JavaScript生成符合Java标准的UUID,并提供了多种优化方法,以提高生成效率和兼容性。 ... [详细]
author-avatar
手机用户2502917001
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有