专题一、ArrayList增删操作技术细节详解
一、索引检查
1)在指定位置插入元素时,第一步都需要检查输入的指定位置是否合法
public void add(int index, E element)
{
rangeCheckForAdd(index);
...
}
==>
private void rangeCheckForAdd(int index)
{
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
分析:rangeCheckForAdd方法用于检查index是否越界。如果该index大于ArrayList元素个数或者小于0时,抛出索引越界异常。
其中outOfBoundsMsg方法,是用来展示IndexOutOfBoundsException detail message。
private String outOfBoundsMsg(int index)
{
return "Index: " + index + ", Size: " + size;
}
2)在指定位置删除元素时,第一步也需要检查输入的索引号是否合法
public E remove(int index)
{
rangeCheck(index);
...
}
==>
private void rangeCheck(int index)
{
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
分析:rangeCheck方法只需检测index索引是否超出ArrayList元素个数。
二、确保容量
1)增加容量
public void add(int index, E element)
{
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1);
...
}
==>
private void ensureCapacityInternal(int minCapacity)
{
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
{
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
其中,minCapacity取与默认值之间的最大值。
ensureExplicitCapacity ==>
private void ensureExplicitCapacity(int minCapacity)
{
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
- size很好理解,就是ArrayList的长度大小,也可理解为ArrayList中已添加的元素个数,这里需要注意:ArrayList允许添加为null的元素,所以null也会占用一份空间。
- elementData就是ArrayList的内部数组实现,它是一个一维对象数组。当通过add方法向ArrayList中添加元素时,这些元素就会被依次存储于elementData这个数组中。 elementData既然是数组,它必然拥有长度length,那么这个数组的长度是否等于ArrayList的size?
这里需要了解一些ArrayList的相关设计概念:
1、作为ArrayList的内部实现数组elementData具备一定的长度(初始值为10),此长度又被称为capacity(容量)。
注意:elementData.length等于elementData.size(),但是ArrayList中的size是记录ArrayList元素的个数,而elementData是用来存放ArrayList的元素。或者说elementData相当于鞋柜容器,它的容器大小==elementData.length==elementData.size(),而ArrayList的size相当于鞋子双数。
参考:List实现之ArrayList
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);
}
- 得到数组的旧容量,然后进行oldCapacity + (oldCapacity >> 1),将oldCapacity 右移一位,其效果相当于oldCapacity /2,我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,
- 然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,
- 再检查新容量是否超出了ArrayList所定义的最大容量,若超出了,则调用hugeCapacity()来比较minCapacity和 MAX_ARRAY_SIZE,如果minCapacity大于最大容量,则新容量则为ArrayList定义的最大容量,否则,新容量大小则为 minCapacity。 (在判断容量是否超过MAX_ARRAY_SIZE的值,MAX_ARRAY_SIZE值为Integer.MAX_VALUE - 8,比int的最大值小8,不知道为什设计,可能方便判断吧。如果已经超过,调用hugeCapacity方法检查容量的int值是不是已经溢出。一般很少用到int最大值的情况,那么多数据也不会用ArrayList来做容器了,估计这辈子没机会见到hugeCapacity运行一次了。)
- 最后确定了新的容量,就使用Arrays.copyOf方法来生成新的数组,copyOf也已经完成了将就的数据拷贝到新数组的工作。(Arrays.copyof(···)与System.arraycopy(···)区别)
需要注意的是,容量拓展,是创建一个新的数组,然后将旧数组上的数组copy到新数组,这是一个很大的消耗,所以在我们使用ArrayList时,最好能预计数据的大小,在第一次创建时就申请够内存。
参考:ArrayList实现原理以及其在jdk1.6和jdk1.7的实现区别
hugeCapacity ==>
private static int hugeCapacity(int minCapacity)
{
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
2)缩小容量
public void trimToSize()
{
modCount++;
if (size < elementData.length)
{
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
专题一、ArrayList增删操作技术细节详解的更多相关文章
- SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)
SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)-DML 1.SQL INSERT INTO 语句(在表中插入) INSERT INTO 语句用于向表中插入新记录. SQL I ...
- SQL Server 表的管理_关于表的操作增删查改的操作的详解(案例代码)
SQL Server 表的管理_关于表的操作增删查改的操作的详解(案例代码) 概述: 表由行和列组成,每个表都必须有个表名. SQL CREATE TABLE 语法 CREATE TABLE tabl ...
- Java8 Stream终端操作使用详解
话不多说,自己挖的坑自己要填完,今天就给大家讲完Java8中Stream的终端操作使用详解.Stream流的终端操作主要有以下几种,我们来一一讲解. forEach() forEachOrdered( ...
- 005-Scala数组操作实战详解
005-Scala数组操作实战详解 Worksheet的使用 交互式命令执行平台 记得每次要保存才会出相应的结果 数组的基本操作 数组的下标是从0开始和Tuple不同 缓冲数组ArrayBuffer( ...
- ASP.NET 操作Cookie详解 增加,修改,删除
ASP.NET 操作Cookie详解 增加,修改,删除 Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密).定义于RFC2109.它 ...
- 在telnet下操作memcache详解(操作命令详解)
这篇文章主要介绍了在telnet下操作memcache详解,telnet下的memcache操作命令详解,需要的朋友可以参考下 在定位问题.测试等时候经常需要对memcache的数据进行一些操作,但是 ...
- Spring Data操作Redis详解
Spring Data操作Redis详解 Redis是一种NOSQL数据库,Key-Value形式对数据进行存储,其中数据可以以内存形式存在,也可以持久化到文件系统.Spring data对Redis ...
- net平台下c#操作ElasticSearch详解
net平台下c#操作ElasticSearch详解 ElasticSearch系列学习 ElasticSearch第一步-环境配置 ElasticSearch第二步-CRUD之Sense Elasti ...
- 安装MACOS操作步骤详解
安装MACOS操作步骤详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 关于安装MAC的操作系统其实大家都知道可以让客服帮忙提供软件上的支持,而且苹果客服都很有礼貌呢,而且非常的 ...
随机推荐
- 最新Blog
应该会长期稳定的 https://b.intmainreturn0.com/
- fzu2109--Mountain Number(数位dp)
Problem Description One integer number x is called "Mountain Number" if: (1) x>0 and x ...
- 自助用户选择VM Network
在VMM中为用户所属角色分配“作者VM网络”权限后,用户才可以在部署虚机的选择不同的VM Network,否则用户只能使用模板上所使用的VM Network,无法进行选择
- android 无线模式下使用ADB调试
改动系统system权限 1. cp sud /system/xbin/sud chmod 755 /system/xbin/sud // note: su chmod 成755 2. cp su / ...
- SQL Server数据库同步SQL
select table_name,COLUMN_NAME,data_TYPE,CHARACTER_OCTET_LENGTH,CHARACTER_MAXIMUM_LENGTH from informa ...
- 【课程分享】基于Lucene4.6+Solr4.6+Heritrix1.14+S2SH实战开发从无到有垂直搜索引擎
对这个课程有兴趣的朋友,能够加我的QQ2059055336和我联系,能够和您分享. 课程介绍:最有前途的软件开发技术--搜索引擎技术 搜索引擎作为互联网发展中至关重要的一种应用,已经成为互联网各个 ...
- Open quote is expected for attribute "{1}" associated with an element type "name".
xml属性必须用引号“”,不能缺少.
- Android(java)学习笔记138:html嵌入到java显示乱码
解决方案: 使用 loadData方法是中文部分会出现乱码,即使指定“utf-8”.“gbk”.“gb2312”也一样. webView.getSettings().setDefaultTextEnc ...
- 什么是aop?
这个命题其实是讲了的,但是之前没有做,发现一些面试会问到,结合自己之前的学习经历.简单把这个问题描述一下. aop是跟oop相对应的一个概念.分别是aspect oriented programmin ...
- Linux coredump学习笔记
初学者笔记:linux的程序在发生异常情况下,会导致进程down,多数服务器会设置生成core文件,本人在实际运营过程中发生过进程不断core,被自动监控拉起,过段时间有core的情况,进而导致磁盘被 ...