【数组】- ArrayList自动扩容机制

  不同的JDK版本的扩容机制可能有差异 实验环境:JDK1.8
  
  扩容机制:
  
  当向ArrayList中添加元素的时候,ArrayList如果要满足新元素的存储超过ArrayList存储新元素前的存储能力,ArrayList会增强自身的存储能力,已达到存储新元素的要求
  
  ArrayList:本质通过内部维护的数组对象进行数据存储
  
  ①:分析ArrayList的add(E)方法
  
  public boolean add(E e) {
  
  ensureCapacityInternal(size + 1); // Increments modCount!!
  
  elementData[size++] = e;
  
  return true;
  
  }
  
  分析:add方法首先通过ensureCapacityInternal()方法确保当前ArrayList维护的数组具有存储新元素的能力,经过处理之后将元素存储在数组elementData的尾部 elementData:ArrayList真正用于存储元素的数组
  
  ②:分析ensureCapacityInternal方法
  
  private void ensureCapacityInternal(int minCapacity) {
  
  if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  
  minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
  
  }
  
  ensureExplicitCapacity(minCapacity);
  
  }
  
  分析:ensureCapacityInternal判断ArrayList默认的元素存储数据是否为空,为空则设置最小要求的存储能力为必要存储的元素和默认存储元素个数的两个数据之间的最大值,然后调用ensureExplicitCapacity方法实现这种最低要求的存储能力
  
  注意:ArrayList的存储空间并不是需要一个创建一个,而是分阶段性的创建,一般会预留存储空间。 例如,如果ArrayList需要存储10个元素,恰好ArrayList只能存储6个元素,剩余4个元素无法存储,ArrayList可能会一次性扩展10个元素,这种ArrayList就有20个元素的存储能力,在存储能力范围内,下次再存放元素,就不需要再次扩容
  
  ③:分析ensureExplicitCapacity方法:
  
  private void ensureExplicitCapacity(int minCapacity) {
  
  modCount++;
  
  // overflow-conscious code
  
  if (minCapacity - elementData.length > 0)
  
  grow(minCapacity);
  
  }
  
  分析:如果最低要求的存储能力>ArrayList已有的存储能力,这就表示ArrayList的存储能力不足,因此需要调用 grow();方法进行扩容 ④:分析grow()方法
  
  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);
  
  }
  
  分析:当ArrayList扩容的时候,首先会设置新的存储能力为原来的1.5倍
  
  int newCapacity = oldCapacity + (oldCapacity www.michenggw.com>> 1);
  
  如果扩容之后还是不能满足要求则MAX_ARRAY_SIZE比较,求取最大值, 如果MAX_ARRAY_SIZE大小的能力还是不能满足则通过hugeCapacity()方法获取ArrayList能允许的最大值:
  
  private static int hugeCapacity(int minCapacity) {
  
  if (minCapacity < 0) // overflow
  
  throw new OutOfMemoryError();
  
  return (minCapacity > MAX_ARRAY_SIZE) ?
  
  Integer.MAX_VALUE :
  
  MAX_ARRAY_SIZE;
  
  }
  
  从hugeCapacity方法看出,ArrayList最大的存储能力:存储元素的个数为整型的范围。 确定ArrayList扩容之后最新的可存储元素个数时,调用 elementData = Arrays.copyOf(elementData, newCapacity); 实现elementData数组的扩容,整个流程就是ArrayList的自动扩容机制工作流程
  
  扩展: ArrayList的自动扩容机制底层借助于System实现
  
  public static native void arraycopy
  
  (Object src, int srcPos,
  
  Object dest, int destPos,
  
  int length);
  
  arraycopy标识为native意味JDK的本地库,不可避免的会进行IO操作,如果频繁的对ArrayList进行扩容,毫不疑问会降低ArrayList的使用性能,因此当我们确定添加元素的个数的时候,我们可以事先知道并指定ArrayList的可存储元素的个数,这样当我们向ArrayList中加入元素的时候,就可以避免ArrayList的自动扩容,从而提高ArrayList的性能
  
  ArrayList含参构造函数:初始化时指定存储元素的能力:
  
  public ArrayList(int initialCapacity) {
  
  if (initialCapacity www.dasheng178.com> 0) {
  
  this.elementData = new Object[initialCapacity];
  
  } else if (initialCapacity == 0) {
  
  this.elementData = EMPTY_ELEMENTDATA;
  
  } else {
  
  throw new IllegalArgumentException(
  
  "Illegal Capacity: "+initialCapacity);
  
  }

原文地址:https://www.cnblogs.com/qwangxiao/p/10359113.html

时间: 2024-08-29 20:36:38

【数组】- ArrayList自动扩容机制的相关文章

ArrayList源码解析(二)自动扩容机制与add操作

目录 1.ArrayList的自动扩容机制 2.add操作 正文 本篇主要分析ArrayList的自动扩容机制,add和remove的相关方法. 作为一个list,add和remove操作自然是必须的. 前面说过,ArrayList底层是使用Object数组实现的.数组的特性是大小固定,这个特性导致的后果之一就是,当ArrayList中成员个数超过capacity后,就需要重新分配一个大的数组,并将原来的成员拷贝到新的数组之中. add操作前都需要保证capacity足够,因此扩容机制和add放

ArrayList的扩容机制

ArrayList的扩容机制: 当向ArrayList中添加元素的时候,ArrayList的存储容量如果满足新元素的容量要求,则直接存储:ArrayList的存储容量如果不满足新元素的容量要求,ArrayList会增强自身的存储能力,以达到存储新元素的要求. 因为不同的JDK版本的扩容机制可能有差异,下面以JDK1.8为例说明一.构造方法 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.element

C#深入研究ArrayList动态数组自动扩容原理

1 void Test1() 2 { 3 ArrayList arrayList = new ArrayList(); 4 int length = 3; 5 for (int i = 0; i < length; i++) 6 { 7 arrayList.Add("TestData"); 8 } 9 Console.WriteLine("count = " + arrayList.Count); 10 Console.WriteLine("capa

【面试必备】透过源码角度一步一步带你分析 ArrayList 扩容机制

一 先从 ArrayList 的构造函数说起ArrayList有三种方式来初始化,构造方法源码如下:/** 默认初始容量大小*/private static final int DEFAULT_CAPACITY = 10; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /*默认构造函数,使用初始容量10构造一个空列表(无参数构造)*/public ArrayList() {this.elementDat

ArrayList和Vector的扩容机制

转自:http://man-yutao.iteye.com/blog/1317446 ArrayList和Vector都是继承了相同的父类和实现了相同的接口.如下 Java代码   public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {} public class ArrayList<E>

Arraylist动态扩容详解

ArrayList 概述 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长. ArrayList不是线程安全的,只能用在单线程环境下. 实现了Serializable接口,因此它支持序列化,能够通过序列化传输: 实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问: 实现了Cloneable接口,能被克隆. 动态扩容 一 初始化 首先有三种方式来初始化: public ArrayList(); 默认的构造器,将会以默认的大小来初始化内部的数

Java常见集合的默认大小及扩容机制

在面试后台开发的过程中,集合是面试的热话题,不仅要知道各集合的区别用法,还要知道集合的扩容机制,今天我们就来谈下ArrayList 和 HashMap的默认大小以及扩容机制. 在 Java 7 中,查看源码可以知道:ArrayList 的默认大小是 10 个元素,HashMap 的默认大小是16个元素(必须是2的幂,为什么呢???下文有解释).这就是 Java 7 中 ArrayList 和 HashMap  类 的代码片段: // from ArrayList.java JDK 1.7 pri

重磅消息!AppCan扩容机制上线,扩大空间随心所欲!

亲爱的AppCan开发者: AppCan在线打包空间扩容机制已经正式上线啦! 开发的项目越来越多,可用的空间却越来越小,怎么办?[扩容空间]让您不再为空间"斤斤计较"! VS 扩容规则: 1.请关注AppCan官方微信号,并在申请原因中注明您的微信号. AppCan微信二维码 2.有至少一个上线的AppCan应用,可申请50M空间,经官方人员审核后即可扩容. 3.任何一个应用安装量超过1000次可申请一次200M空间. 4.3个月内不可重复申请,且3个月后需凭借其他符合上述要求的应用才

数组/切片以及扩容的概念 | Go语言基础

package main // 当前包声明 func main() { // 程序的入口 // 数组 // 存储一组相同数据类型的数据结构 // 连续开辟内存,数组的地址其实是数组的首地址 // 一旦定义,大小不能改变 // 创建数组 ==> 访问数组(赋值,取值) var arr [4] int arr[0] = 1 arr[1] = 2 arr[2] = 3 arr[3] = 4 fmt.Println(arr) // 未赋值为默认值 // 遍历数组 for i:=0;i<len(arr)