数组(定长,有序的,随机访问)。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_ELEMENTDATAEMPTY_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);
}

分析

  1. add函数,可以看出来,每次扩容都是本身的 0.5
  2. 最大可以扩容到 Intege最大值,但也是在实际元素数量真的超过 MAX_ARRAY_SIZE的情况下。
  3. 建立不超过MAX_ARRAY_SIZE的原因是 OutOfMemoryError: Requested array size exceeds VM limit
  4. 为了避免开辟过多的数组空间,建立选择带参数的构造函数,以量申请。

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

注意事项

  1. 禁止在 for``foreach里删除元素。
  2. ArrayList在多线程环境中是不安全的

ArrayList常用Api分析及注意事项的更多相关文章

  1. ArrayList源码分析和实例应用

    1.ArrayList介绍 ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAcces ...

  2. Java ArrayList常用接口介绍及示例

    Java List 常用类型 类型 特征 ArrayList 随机访问元素快:中间插入与删除元素较慢:操作不是线程安全的 LinkedList 中间插入与删除操作代价较低,提供优化的顺序访问:随机访问 ...

  3. List容器——ArrayList及常用API

    List: ①   List容器是有序的collection(也称为序列).此接口的用户可以对List容器中每个元素的插入位置进行精确地控制.用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜 ...

  4. Java常用API(ArrayList类)

    Java常用API(ArrayList类) 我们为什么要使用ArrayList类? 为了更加方便的储存对象,因为使用普通的数组来存储对象太过麻烦了,因为数组的一个很大的弱点就是长度从一开始就固定了,所 ...

  5. Java 常用API(二)

    目录 Java 常用API(二) 1. Object类 2. Date类 概述 构造方法和成员方法 3. DateFormat类 概述 SimpleDateFormat类 练习 4. Calendar ...

  6. Java 常用API(一)

    目录 Java 常用API(一) 1. Scanner类 引用类型的一般使用步骤 Scanner的使用步骤 例题 2. 匿名对象 概述 匿名对象作为方法的参数 匿名对象作为方法的返回值 3. Rand ...

  7. 19 常用API

    API 什么是API? API (Application Programming Interface) :应用程序编程接口 简单来说:就是Java帮我们已经写好的一些方法,我们直接拿过来用就可以了 1 ...

  8. Java基础语法Day_07(1-3 常用API第一部分)

    常用API第一部分 第1节 Scanner类         day07_01_API概述和使用步骤(使用最基本的三个步骤 搜索 构造方法  方法) day07_02_Scanner概述及其API文档 ...

  9. 人工智能常用 API

    人工智能常用 API 转载  2016年07月13日 19:17:27 2047 机器学习与预测 1.AlchemyAPI  在把数据由非结构化向结构化的转化中运用得较多.用于社交媒体监控.商业智能. ...

随机推荐

  1. 小程序TAB列表切换内容动态变化,scrollview高度根据内容动态获取

    滑动tab选项卡 一.在小程序里面tab选项卡是用的是自带的swiper组件,下面直接上代码 <view class="container"> <view cla ...

  2. 前端系列——快速理解babel6配置过程

    繁琐的配置? 你能快速读懂babel的官方文档吗? 你能根据官方文档快速配置好babelrc吗? 你能明白自己需要哪些插件吗? 没有搞明白这3个问题,请往下看. 快速理解babel 6 来看一张让人颤 ...

  3. 【Android开发】Android 颜色透明度换算

    透明度 透明度分为256阶(0-255),计算机上用16进制表示为(00-ff). 透明就是0阶,不透明就是255阶,如果50%透明就是127阶(256的一半当然是128,但因为是从0开始,所以实际上 ...

  4. Linux安装JDK报错

    报错内容: tar (child): jdk-8u141-linux-x64.tar.gz: Cannot open: No such file or directory tar (child): E ...

  5. java中单态模式或单例模式(Singleton)有什么意义?

    8.单态模式或单例模式(Singleton) 单态模式有什么用呢?想一下Adobe Photoshop ,处理两张图,会启动两个photoshop吗?多耗费内存呀! ( Consider Adobe ...

  6. Node自动重启工具 nodemon

    为什么要使用 在编写调试Node.js项目,修改代码后,需要频繁的手动close掉,然后再重新启动,非常繁琐.现在,我们可以使用nodemon这个工具,它的作用是监听代码文件的变动,当代码改变之后,自 ...

  7. 解决stram++的host代理443端口被占用的问题(电脑有虚拟机进!!)

    解决stram++的host代理443端口被占用的问题 一.steam++ 最近在用steam++这个开源且功能强大的加速器,过多就不介绍了 主页地址跳转:Steam++ - 主页 (steampp. ...

  8. Elasticsearch8.1-ElasticsearchClient-Java客户端简单增删查改-随笔

    环境准备 Springboot 基本环境 自行前往https://start.spring.io/ 构建一个即可 Elasticsearch服务端 简单说下windows版本的安装  https:// ...

  9. rancher 添加集群

    用rancher的管理账户登录rancher控制台首先创建用户 jinzs,后面用户绑定到要添加的集群上的 其次点全局,出现集群列表 >点添加集群 这里集群名称任意,只要你知道,该名称要对应实际 ...

  10. Codeforces Round #721 (Div. 2)A. And Then There Were K(位运算,二进制) B1. Palindrome Game (easy version)(博弈论)

    半个月没看cf 手生了很多(手动大哭) Problem - A - Codeforces 题意 给定数字n, 求出最大数字k, 使得  n & (n−1) & (n−2) & ...