ArrayList详解-源码分析

ArrayList详解-源码分析 1. 概述

在平时的开发中,用到最多的集合应该就是ArrayList了,本篇文章将结合源代码来学习ArrayList。

ArrayList是基于数组实现的集合列表

支持任意性的访问(可根据索引直接得到你想要的元素)

线程不安全

支持动态扩容

查询快,增删慢

...

这些大家应该都很清楚,下面根据源代码来深入分析一下ArrayList。

2. ArrayList类声明

源代码如下所示:

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

初步分析:

ArrayList类继承于AbstractList抽象类

ArrayList类实现了List、RandomAccess、Cloneable、Serializable接口

继续分析一下:

AbstractList抽象类其实已经实现了Collection接口中大部分方法

实现了RandomAccess接口,所以支持任意性访问(随机访问)

实现了Cloneable接口,说明重写了 clone()方法,支持拷贝(Cloneable 接口只是个合法调用 clone() 的标识(marker-interface),一个对象想调用clone()方法,则该类必须实现Cloneable 接口,否则会报错 CloneNotSupportedException )

实现了Serializable接口,支持序列化操作

3. 成员变量

源代码如下所示:

private static final long serialVersionUID = 8683452581122892189L; /** * Default initial capacity. */ private static final int DEFAULT_CAPACITY = 10; /** * Shared empty array instance used for empty instances. */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * Shared empty array instance used for default sized empty instances. We * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when * first element is added. */ private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-private to simplify nested class access private int size;

初步思考:

一共有6个变量,各自的作用?

有两个空数组,只是命名不一样,为什么?

继续分析:

各个变量的作用:

serialVersionUID: 序列化版本号

DEFAULT_CAPACITY:默认容量大小

EMPTY_ELEMENTDATA:空数组时的引用

DEFAULTCAPACITY_EMPTY_ELEMENTDATA:初始化时默认的空数组

elementData:实际存储集合元素的数组

size:实际元素的数量(int类型默认值为0)

两个空数组:

分别用于默认初始化和传入容量时的初始化

4. 构造方法

源代码如下所示:

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) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }

初步思考:

提供了三个构造方法

分别对应无参构造、指定集合容量的构造以及通过Collection的子类来构造一个ArrayList对象

继续分析:

无参构造:

直接将DEFAULTCAPACITY_EMPTY_ELEMENTDATA的空数组赋值给elementData(注意:此时ArrayList的数组长度还是0)

指定容量构造:

参数大于0: 创建一个该参数大小的数组,赋值给elementData

参数等于0: 将成员变量EMPTY_ELEMENTDATA数组赋值给elementData

参数小于0: 抛出异常

传入Collection子类对象构造:

public ArrayList(Collection<? extends E> c) { /** *将传入的集合转换为一个Object类型的数组,并将此数组的引用赋给elementData */ elementData = c.toArray(); if ((size = elementData.length) != 0) {// 转换后的数组不为空时 /** * 判断转换后的数组是不是Object[]数组 * 如果不是的话,就把它复制为一个Object[]数组,进行赋值 */ if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // 转换后的数组为空,用成员变量EMPTY_ELEMENTDATA来辅助 this.elementData = EMPTY_ELEMENTDATA; } }

toArray()方法源代码如下:

public Object[] toArray() { return Arrays.copyOf(elementData, size); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgdfpj.html