数码控科技猎奇Iphone动漫星座游戏电竞lolcosplay王者荣耀攻略allcnewsBLOGNEWSBLOGASKBLOGBLOGZSK全部技术问答问答技术问答it问答代码软件新闻开发博客电脑/网络手机/数码笔记本电脑互联网操作系统软件硬件编程开发360产品资源分享电脑知识文档中心IT全部全部分类全部分类技术牛文全部分类教程最新网页制作cms教程平面设计媒体动画操作系统网站运营网络安全服务器教程数据库工具网络安全软件教学vbscript正则表达式javascript批处理更多»编程更新教程更新游戏更新allitnewsJava新闻网络医疗信息化安全创业站长电商科技访谈域名会议专栏创业动态融资创投创业学院 / 产品经理创业公司人物访谈营销开发数据库服务器系统虚拟化云计算嵌入式移动开发作业作业1常见软件all电脑网络手机数码生活游戏体育运动明星影音休闲爱好文化艺术社会民生教育科学医疗健康金融管理情感社交地区其他电脑互联网软件硬件编程开发360相关产品手机平板其他电子产品摄影器材360硬件通讯智能设备购物时尚生活常识美容塑身服装服饰出行旅游交通汽车购房置业家居装修美食烹饪单机电脑游戏网页游戏电视游戏桌游棋牌游戏手机游戏小游戏掌机游戏客户端游戏集体游戏其他游戏体育赛事篮球足球其他运动球类运动赛车健身运动运动用品影视娱乐人物音乐动漫摄影摄像收藏宠物幽默搞笑起名花鸟鱼虫茶艺彩票星座占卜书画美术舞蹈小说图书器乐声乐小品相声戏剧戏曲手工艺品历史话题时事政治就业职场军事国防节日风俗法律法规宗教礼仪礼节自然灾害360维权社会人物升学入学人文社科外语资格考试公务员留学出国家庭教育学习方法语文物理生物工程学农业数学化学健康知识心理健康孕育早教内科外科妇产科儿科皮肤科五官科男科整形中医药品传染科其他疾病医院两性肿瘤科创业投资企业管理财务税务银行股票金融理财基金债券保险贸易商务文书国民经济爱情婚姻家庭烦恼北京上海重庆天津黑龙江吉林辽宁河北内蒙古山西陕西宁夏甘肃青海新疆西藏四川贵州云南河南湖北湖南山东江苏浙江安徽江西福建广东广西海南香港澳门台湾海外地区

对Java 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 >> 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 > 0) {
   this.elementData = new Object[initialCapacity];
  } else if (initialCapacity == 0) {
   this.elementData = EMPTY_ELEMENTDATA;
  } else {
   throw new IllegalArgumentException(
   "Illegal Capacity: "+initialCapacity);            
  }
 }

以上这篇对Java ArrayList的自动扩容机制示例讲解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:


  • 本文相关:
  • arraylist的自动扩充机制实例解析
  • java中arraylist动态扩容方法详解
  • java arraylist扩容问题实例详解
  • spring task定时任务的配置和使用详解
  • java线程之线程同步synchronized和volatile详解
  • java中使用filter控制用户登录权限具体实例
  • java使用poi将word转换为html
  • my eclipse 端口占用(9360)问题解决办法
  • java处理interruptedexception异常的理论与实践
  • spring boot 自动配置的实现
  • mybatis利用ognl表达式处理动态sql的方法教程
  • springboot2.x集成redis集群(lettuce)连接的方法
  • java递归 遍历目录的小例子
  • 免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved