一、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类的更多相关文章

  1. Java基础系列-ArrayList

    原创文章,转载请标注出处:<Java基础系列-ArrayList> 一.概述 ArrayList底层使用的是数组.是List的可变数组实现,这里的可变是针对List而言,而不是底层数组. ...

  2. Java基础-DButils工具类(QueryRunner)详解

    Java基础-DButils工具类(QueryRunner)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC ...

  3. Java基础之File类的使用

    Java基础之File类的使用 1.File类的构造方法和常用方法 2.对File中listFile(FileNameFilter name)学习 3.与File文件类相关的实现 File类的构造方法 ...

  4. Java常用API(ArrayList类)

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

  5. Java基础(44):ArrayList使用详解

    1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处:    a.动态的增加和减少元素    b.实现了IColle ...

  6. Java基础:Object类中的equals与hashCode方法

    前言 这个系列的文章主要用来记录我在学习和复习Java基础知识的过程中遇到的一些有趣好玩的知识点,希望大家也喜欢. 一切皆对象   对于软件工程来说面向对象编程有一套完整的解决方案:OOA.OOD.O ...

  7. 【Java基础】常用类

    常用类 字符串相关的类 String类:代表字符串,使用一对 "" 引起来表示. public final class String implements java.io.Seri ...

  8. java基础-01代理类

    简单的代理类实现案例主实现类:ProxyTestimport java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;im ...

  9. java基础之常用类1

    java基础 以下内容为本人的学习笔记,如需要转载,请声明原文链接   java常用类: 1.内部类 2.Object类 3.Object类常用方法 4.包装类 5.String类 6.BigDeci ...

随机推荐

  1. day13 python生成器函数 推导式 生成器

    day13 python   一.生成器     生成器的本质就是迭代器     生成器的特点和迭代器一样. 取值方式和迭代器一样(__next__())     由生成器函数或生成器表达式来创建   ...

  2. 你了解SEO中的时效性吗?

    你了解SEO中的时效性吗? 本文摘自web前端早读课,侵删. 前言 最近刚好在负责一个新项目,App在还没上线的前提上,PC/WAP可以优先部署相关SEO,这样在后续的推广中得以运用.今日早读文章由腾 ...

  3. css3 渐变色兼容移动端

    .group_1 background #1a78f3 // 兼容不显示渐变色的浏览器 background: linear-gradient(180deg, #1a78f3 , #fff); bac ...

  4. PHP上传文件和下载

    PHP 中文件上传的基础知识: 1)客户端 form 表单设置 必须设置的 form 表单项: <!DOCTYPE html> <html> <head> < ...

  5. MySQL-几种关联

    左表t1: DROP TABLE IF EXISTS t1; )); ,'t1a'); ,'t1b'); ,'t1c'); ,'t1d'); ,'t1f'); 右表 t2: DROP TABLE IF ...

  6. Day One-Python基础

    Python第一节 安装教程就不发了,太心累了!大家可以上百度查,网上都会有 python种类 JavaPython cPython pypy 两种编码  字节码 和 机器码 unicode utf8 ...

  7. Nacos Config客户端与Spring Boot、Spring Cloud深度集成

    目录 Nacos与Spring Boot集成 @NacosPropertySource和@NacosValue com.alibaba.nacos.spring.core.env.NacosPrope ...

  8. gradle 排除jar

    排除fastjson的包,其他同理compile('com.qq.sdk:core:2.0.3') { exclude group: 'com.alibaba'}

  9. VC2008中处理CStatic控件的单击STN_CLICKED消息

    在MFC中,静态文本CStatic控件主要是用来作为标签,即作为注释用的.一般情况下不做消息响应.但是有时特殊情况下会做一些消息响应,比如处理单击事件STN_CLICKED等. 在VC2008下使用M ...

  10. Python matplotlib 交互模式

    在交互模式下一定要执行plt.pause(0.0001)  才会显示图像