Java基础之ArrayList类
一、ArrayList
ArrayList继承了AbstractList分别实现了List、RandomAccess(随机访问)、Cloneable(可被克隆(复制的意思))、
Serializable(可序列化)
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
1.1、RandomAccess(随机访问)
该接口是List实现来指示它们支持快速(通常是固定时间)随机访问。主这个接口的目的是允许通用算法改变它们行为提供良好的性能时,适用于随机或顺序访问列表。
操作随机访问列表的最佳算法
(如 ArrayList),
应用于可产生二次行为顺序访问列表(如LinkedList)。
通用的列表建议使用算法检查给定列表是否为
instanceof这个接口之前,应用的算法会
如果应用于顺序访问列表,则性能较差,
并在必要时改变他们的行为,以确保他们的行为是可接受的
性能。
例子:
若是列表很大时,某些List实现提供渐进的线性访问时间,但实际上的访问时间是固定的。这样的List实现通常应该实现此接口。实际经验证明,如果是下列情况,则
List实现
对于类的典型实例,这个循环:
for (int i=0, n=list.size(); i < n; i++)
list.get(i);
运行速度比这个循环快:
for (Iterator i=list.iterator(); i.hasNext(); )
i.next();
1.2实现Cloneable接口的作用
类实现了Cloneable接口,以向Object.clone()方法表明,该方法对该类的实例进行字段对字段的复制是合法的。
没实现Cloneable接口的实例上调用Object(对象)的clone(克隆)方法将导致抛出异常CloneNotSupportedException。
按照惯例,实现此接口的类应该使用公共方法重写对象Object.clone(它是受保护的)。有关覆盖此方法的详细信息,请参阅java.lang.Object.clone()。
请注意,此接口不包含clone(克隆)方法。因此,仅凭对象实现此接口这一事实是不可能clone(克隆)对象的。即使反射性地调用clone(克隆)方法,也不能保证它会成功。
1.3实现Serializable接口的作用:
类的可序列化性是由实现java.io的类来启用的。Serializable接口。不实现此接口的类将不会对其任何状态进行序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
2.ArrayList.class
2.1 ArrayList成员变量
/**
* 声明serialVersionUID的值,确保serialVersionUID值跨不同JAVA编译器实现的一致性(版本的兼容性)。
* 强烈建议使用Private修饰符显示声明serialVersionUID
* serialVersionUID字段作为继承成员没有用处
*/
private static final long serialVersionUID = 8683452581122892189L;
/**
* 默认初始容量。(ArrayList底层是数组结构)
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 用于空实例的共享空数组实例。(当指定数组的容量为0时使用这个常量赋值)
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 用于默认大小的空实例的共享空数组实例。我们
* 将其与EMPTY_ELEMENTDATA区分开来,以了解何时膨胀多少
* 添加第一个元素。(默认空参构造函数时使用这个常量赋值)
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 存储ArrayList元素的数组缓冲区。
* ArrayList的容量是这个数组缓冲区的长度。
* 即元素数组:真正存放数据的对象数组,transient标识不被序列化
*/
transient Object[] elementData; // 非私有以简化嵌套类访问
/**
* ArrayList的大小(它包含的元素的数量)。
*/
private int size;
/**
* 分配的数组的最大值。
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 修改次数
* /
protected transient int modCount = 0;
2.2 ArrayList构造方法
/**
*指定初始容量的大小。
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {//在容量大于零的条件下,指定多大容量就是多大
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {//没有指定容量大小,则为空数组
this.elementData = EMPTY_ELEMENTDATA;//构造一个空的List其size为DEFAULT_CAPACITY = 10的空列表。
} else {//如果指定容量大小为负责,抛出异常IllegalArgumentException
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* 构造一个空的List其size为DEFAULT_CAPACITY = 10的空列表。
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 传入一个Collection初始化ArrayList
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();//把给定的集合转换成Object[]数组
if ((size = elementData.length) != 0) {//判断转换成的数组不为空
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)//判断集合存的元素不是Object
elementData = Arrays.copyOf(elementData, size, Object[].class);
//复制的数组,返回副本的长度,返回副本的类→→→新的数组[]
} else {
//elementData的length为空,直接将ArrayList的数组转为空数组
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
//将ArrayList实例的容量调整为列表的当前大小。
//应用程序可以使用此操作最小化ArrayList实例的存储。
public void trimToSize() {
modCount++;//修改次数+1
if (size < elementData.length) {
//如果底层数组的length为空则置为EMPTY_ELEMENTDATA
//否则使用Arrays的方法对复制元素
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
2.3常用方法add
2.3.1add(E a)与add(int index,E element);
//将指定的元素追加到此列表的末尾。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;//元素添加到此列表中
return true;
}
add调用了函数→ensureCapacityInternal(int size)代码如下:
private void ensureCapacityInternal(int minCapacity) {
//若当前数组是空数组
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//则比较加入的个数与默认个数(10)比较,取较大值
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
我的理解是此函数是确认ArrayList底层数组elementData有适合的大小;
然后ensureCapacityInternal(int minCapacity)函数调用
ensureExplicitCapacity(minCapacity)代码如下:
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//修改次数+1
// overflow-conscious code(溢出)
//判断数组真实元素个数加1后的长度与当前数组长度大小关系,
//如果小于0,返回,如果大于0,则
//调用grow(minCapacity)方法
if (minCapacity - elementData.length > 0)//数组放不下
grow(minCapacity);//扩容
}
ensureExplicitCapacity(int minCapacity)此函数调用了
grow(minCapacity)函数
/**
* 增加容量,以确保它至少可以容纳由最小容量参数指定的元素数量。
*/
private void grow(int minCapacity) {
// overflow-conscious code
//老容量
int oldCapacity = elementData.length;
//新容量为原来的1.5倍
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动态增大主要是依赖于外汇常见问题grow(int minCapacity)方法调用
Arrays.copyOf(elementData, newCapacity);
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
总结:
add函数的调用过程
ArrayList 内部使用数组存储元素,当数组长度不够时进行扩容,每增加自身一半的空间,ArrayList不会进行缩小容容量;
ArrayList默认初始化容量为10,底层是数组结构;
线程不安全;
Key有序,value不可重复的;
ArrayList 支持随机访问,通过索引访问元素快,时间复杂度为O(1);
ArrayList 添加元素到尾部快,平均时间复杂度为O(1);
ArrayList 添加元素到中间比较慢,因为要搬移元素,平均时间复杂度为O(n);
ArrayList 从尾部删除元素快,平均时间复杂度为O(1);
ArrayList 从中间删除元素比较慢,因为要搬移元素,平均时间复杂度为O(n);
————————————————
原文链接:https://blog.csdn.net/weixin_44903953/article/details/102880906
Java基础之ArrayList类的更多相关文章
- Java基础系列-ArrayList
原创文章,转载请标注出处:<Java基础系列-ArrayList> 一.概述 ArrayList底层使用的是数组.是List的可变数组实现,这里的可变是针对List而言,而不是底层数组. ...
- Java基础-DButils工具类(QueryRunner)详解
Java基础-DButils工具类(QueryRunner)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC ...
- Java基础之File类的使用
Java基础之File类的使用 1.File类的构造方法和常用方法 2.对File中listFile(FileNameFilter name)学习 3.与File文件类相关的实现 File类的构造方法 ...
- Java常用API(ArrayList类)
Java常用API(ArrayList类) 我们为什么要使用ArrayList类? 为了更加方便的储存对象,因为使用普通的数组来存储对象太过麻烦了,因为数组的一个很大的弱点就是长度从一开始就固定了,所 ...
- Java基础(44):ArrayList使用详解
1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: a.动态的增加和减少元素 b.实现了IColle ...
- Java基础:Object类中的equals与hashCode方法
前言 这个系列的文章主要用来记录我在学习和复习Java基础知识的过程中遇到的一些有趣好玩的知识点,希望大家也喜欢. 一切皆对象 对于软件工程来说面向对象编程有一套完整的解决方案:OOA.OOD.O ...
- 【Java基础】常用类
常用类 字符串相关的类 String类:代表字符串,使用一对 "" 引起来表示. public final class String implements java.io.Seri ...
- java基础-01代理类
简单的代理类实现案例主实现类:ProxyTestimport java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;im ...
- java基础之常用类1
java基础 以下内容为本人的学习笔记,如需要转载,请声明原文链接 java常用类: 1.内部类 2.Object类 3.Object类常用方法 4.包装类 5.String类 6.BigDeci ...
随机推荐
- day13 python生成器函数 推导式 生成器
day13 python 一.生成器 生成器的本质就是迭代器 生成器的特点和迭代器一样. 取值方式和迭代器一样(__next__()) 由生成器函数或生成器表达式来创建 ...
- 你了解SEO中的时效性吗?
你了解SEO中的时效性吗? 本文摘自web前端早读课,侵删. 前言 最近刚好在负责一个新项目,App在还没上线的前提上,PC/WAP可以优先部署相关SEO,这样在后续的推广中得以运用.今日早读文章由腾 ...
- css3 渐变色兼容移动端
.group_1 background #1a78f3 // 兼容不显示渐变色的浏览器 background: linear-gradient(180deg, #1a78f3 , #fff); bac ...
- PHP上传文件和下载
PHP 中文件上传的基础知识: 1)客户端 form 表单设置 必须设置的 form 表单项: <!DOCTYPE html> <html> <head> < ...
- MySQL-几种关联
左表t1: DROP TABLE IF EXISTS t1; )); ,'t1a'); ,'t1b'); ,'t1c'); ,'t1d'); ,'t1f'); 右表 t2: DROP TABLE IF ...
- Day One-Python基础
Python第一节 安装教程就不发了,太心累了!大家可以上百度查,网上都会有 python种类 JavaPython cPython pypy 两种编码 字节码 和 机器码 unicode utf8 ...
- Nacos Config客户端与Spring Boot、Spring Cloud深度集成
目录 Nacos与Spring Boot集成 @NacosPropertySource和@NacosValue com.alibaba.nacos.spring.core.env.NacosPrope ...
- gradle 排除jar
排除fastjson的包,其他同理compile('com.qq.sdk:core:2.0.3') { exclude group: 'com.alibaba'}
- VC2008中处理CStatic控件的单击STN_CLICKED消息
在MFC中,静态文本CStatic控件主要是用来作为标签,即作为注释用的.一般情况下不做消息响应.但是有时特殊情况下会做一些消息响应,比如处理单击事件STN_CLICKED等. 在VC2008下使用M ...
- Python matplotlib 交互模式
在交互模式下一定要执行plt.pause(0.0001) 才会显示图像