ArrayList常用Api分析及注意事项
数组(定长,有序的,随机访问)。ArrayList是Java在数组的基础上进行衍生出来的Java里的一种数据结构,它在拥有数据的特性之外,增加了可变性 (动态数组)。
属性
属性 | 备注 |
---|---|
DEFAULT_CAPACITY | 默认初始大小 |
EMPTY_ELEMENTDATA | 空数组,申明了长度可能为0 |
DEFAULTCAPACITY_EMPTY_ELEMENTDATA | 空数组 (无参构造时候的默认值) |
elementData | 承认数组元素 |
size | 数组元素数量,注意和Lenth的 |
三种构造初始化
/**
带有参数的构造方法,
如果长度为0 则给一个默认的常量。
*/
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);
}
}
/**
直接给一个默认的空数组
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public ArrayList(Collection<? extends E> c) {
Object[] a = c.toArray();
if ((size = a.length) != 0) {
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
// replace with empty array.
elementData = EMPTY_ELEMENTDATA;
}
}
分析
以上三种构建,两种有参,一种无参。主要区别就是 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
和 EMPTY_ELEMENTDATA
在不同场景分别给值。
EMPTY_ELEMENTDATA
是带参数的构建函数里长度为0的默认共享数组
DEFAULTCAPACITY_EMPTY_ELEMENTDATA
是不带参数构造函数里长度为0的共享数组
对比老版本的JDK来看,会对初始化数组的时候解决是数度长度为空的情况下会 new Object[initialCapatity]
的情况,减少不必要的内存开支。
在扩容机制也会针对不同的构造出的数组进行不同的扩容机制。
Add方法
public boolean add(E e) {
//确保容量够不够,扩容机制
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
// step 1
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// step 2. 计算容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//判断是否是无参构造来的,为10个容量大小
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//否则就给即将增长的长度
return minCapacity;
}
// step 3
private void ensureExplicitCapacity(int minCapacity) {
//修改次数
modCount++;
// 即将增长的长度比现的数组长度大就扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// step 4
private void grow(int minCapacity) {
//原始长度
int oldCapacity = elementData.length;
//新长度 = 原始长度 + (原始长度/2)
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//尽量不扩容到 Intege 的最大值, 因为有些Vm的设计超过 MAX_ARRAY_SIZE 可能会 OOM错误 (OutOfMemoryError: Requested array size exceeds VM limit)
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);
}
分析
- 从
add
函数,可以看出来,每次扩容都是本身的 0.5 倍 - 最大可以扩容到
Intege
最大值,但也是在实际元素数量真的超过MAX_ARRAY_SIZE
的情况下。 - 建立不超过
MAX_ARRAY_SIZE
的原因是OutOfMemoryError: Requested array size exceeds VM limit
- 为了避免开辟过多的数组空间,建立选择带参数的构造函数,以量申请。
Remove方法
借助了系统函数
/**
* 第一个参数是要被复制的数组
*
* 第二个参数是被复制的数字开始复制的下标
*
* 第三个参数是目标数组,也就是要把数据放进来的数组
*
* 第四个参数是从目标数组第几个下标开始放入数据
*
* 第五个参数表示从被复制的数组中拿几个数值放到目标数组中
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
把最后一个元素置为null
, size = size -1
elementData[--size] = null; // clear to let GC do its work
注意事项
- 禁止在
for``foreach
里删除元素。 ArrayList
在多线程环境中是不安全的
ArrayList常用Api分析及注意事项的更多相关文章
- ArrayList源码分析和实例应用
1.ArrayList介绍 ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAcces ...
- Java ArrayList常用接口介绍及示例
Java List 常用类型 类型 特征 ArrayList 随机访问元素快:中间插入与删除元素较慢:操作不是线程安全的 LinkedList 中间插入与删除操作代价较低,提供优化的顺序访问:随机访问 ...
- List容器——ArrayList及常用API
List: ① List容器是有序的collection(也称为序列).此接口的用户可以对List容器中每个元素的插入位置进行精确地控制.用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜 ...
- Java常用API(ArrayList类)
Java常用API(ArrayList类) 我们为什么要使用ArrayList类? 为了更加方便的储存对象,因为使用普通的数组来存储对象太过麻烦了,因为数组的一个很大的弱点就是长度从一开始就固定了,所 ...
- Java 常用API(二)
目录 Java 常用API(二) 1. Object类 2. Date类 概述 构造方法和成员方法 3. DateFormat类 概述 SimpleDateFormat类 练习 4. Calendar ...
- Java 常用API(一)
目录 Java 常用API(一) 1. Scanner类 引用类型的一般使用步骤 Scanner的使用步骤 例题 2. 匿名对象 概述 匿名对象作为方法的参数 匿名对象作为方法的返回值 3. Rand ...
- 19 常用API
API 什么是API? API (Application Programming Interface) :应用程序编程接口 简单来说:就是Java帮我们已经写好的一些方法,我们直接拿过来用就可以了 1 ...
- Java基础语法Day_07(1-3 常用API第一部分)
常用API第一部分 第1节 Scanner类 day07_01_API概述和使用步骤(使用最基本的三个步骤 搜索 构造方法 方法) day07_02_Scanner概述及其API文档 ...
- 人工智能常用 API
人工智能常用 API 转载 2016年07月13日 19:17:27 2047 机器学习与预测 1.AlchemyAPI 在把数据由非结构化向结构化的转化中运用得较多.用于社交媒体监控.商业智能. ...
随机推荐
- CSS 3-浮动、定位
文档流 文档流是一种默认定位方式,在文档流中元素框的位置由元素在html中的位置决定,文档流中元素的position属性为默认的static或继承来的static并按照普通流定位.块级元素独占一行,自 ...
- 访问控制中默认,public,private,protected区别?
2.继承的访问控制: (比如一个类中的protected成员对于"不同的包中的非子类"是不可见的. 说明:1.任何public的内容可以被从任何地方访问. 2.private的成员 ...
- es6语法之模版字符串
//es6语法之`${}`以及vue语法 `${ }` (模版字符串)const name = '小缘' const age = 14 console.info(`大家好,我叫${name},今年${ ...
- 分库分表实现方式Client和Proxy,性能和维护性该怎么选?
大家好,我是[架构摆渡人],一只十年的程序猿.这是分库分表系列的第一篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友. 其实这个系列有录过视频给大家学习,但很多 ...
- CSS3中有哪些新特性
新增各种CSS选择器 (: not(.input):所有 class 不是"input"的节点) 圆角 (border-radius:8px) 多列布局 (multi-column ...
- LC-76
给你一个字符串 s .一个字符串 t .返回 s 中涵盖 t 所有字符的最小子串.如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" . 注意: 对于 t 中重复字符 ...
- 测试开发【Mock平台】04实战:前后端项目初始化与登录鉴权实现
[Mock平台]为系列测试开发教程,从0到1编码带你一步步使用Spring Boot 和 Antd React 框架完成搭建一个测试工具平台,希望作为一个实战项目能为你的测试开发学习有帮助. 一.后端 ...
- springboot项目找不到符号问题以及模块聚合项目maven插件使用的相关问题
问题如图 更换maven,清空缓存重新导入依赖依然无效后 解决方法: 方式一:删除项目中.idea文件夹,重新打开项目,选中jdk版本 ,重新导入依赖即可. 最近又遇到找不到符号问题,本地运行没问题, ...
- Jenkins+Allure测试报告+飞书机器人发送通知
一.前言 之前讲了jenkins如何设置定时任务执行脚本,结合实际情况,本篇讲述在jenkins构建成功后,如何生成测试报告,以及推送飞书(因为我公司用的是飞书,所以是发送到飞书机器人). 本次实践搞 ...
- SpringBoot扩展点EnvironmentPostProcessor
一.背景 之前项目中用到了Apollo配置中心,对接Apollo配置中心后,配置中心的属性就可以在程序中使用了,那么这个是怎么实现的呢?配置中心的属性又是何时加载到程序中的呢?那么我们如果找到了这个是 ...