目录
ArrayList的特点:
- ArrayList自己实现了序列化和反序列化的方法,因为它自己实现了 private void writeObject(java.io.ObjectOutputStream s)和 private void readObject(java.io.ObjectInputStream s) 方法
- ArrayList基于数组方式实现,无容量的限制(会扩容)
- 添加元素时可能要扩容(所以最好预判一下),删除元素时不会减少容量(若希望减少容量,trimToSize()),删除元素时,将删除掉的位置元素置为null,下次gc就会回收这些元素所占的内存空间。
- 线程不安全
- add(int index, E element):添加元素到数组中指定位置的时候,需要将该位置及其后边所有的元素都整块向后复制一位
- get(int index):获取指定位置上的元素时,可以通过索引直接获取(O(1))
- remove(Object o)需要遍历数组
- remove(int index)不需要遍历数组,只需判断index是否符合条件即可,效率比remove(Object o)高
- contains(E)需要遍历数组
- 使用iterator遍历可能会引发多线程异常
1 简介
ArrayList结构
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
1、AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。
2、ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。
3、ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
4、ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。
5、ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输
注意:
和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList,或者使用Collections工具类的synchronizedList方法将其包装
源码分析
属性:
//序列化id private static final long serialVersionUID = 8683452581122892189L; //默认初始容量 private static final int DEFAULT_CAPACITY = 10; //一个空数组,当用户指定ArrayList容量为0时,返回该数组 private static final Object[] EMPTY_ELEMENTDATA = {}; /** * 一个空数组实例,当用户没有指定 ArrayList 的容量时(即调用无参构造函数),返回的是该数组 * - 当用户第一次添加元素时,该数组将会扩容,变成默认容量为 10(DEFAULT_CAPACITY) 的一个数组 * 它与 EMPTY_ELEMENTDATA 的区别就是:该数组是默认返回的,而后者是在用户指定容量为 0 时返回 */ private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //当前数据对象存放地方,当前对象不参与序列化 //这个关键字最主要的作用就是当序列化时,被transient修饰的内容将不会被序列化 transient Object[] elementData; // non-private to simplify nested class access //ArrayList实际存储的数据数量 private int size;
构造方法:
/** * 创建一个初始容量的、空的ArrayList */ 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); } } /** * 无参构造函数: * - 创建一个 空的 ArrayList,此时其内数组缓冲区 elementData = {}, 长度为 0 * - 当元素第一次被加入时,扩容至默认容量 10 */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } /** * 建一个包含collection的ArrayList * 方法:Arrays.copyOf(elementData, size, Object[].class) * 根据class的类型来决定是new 还是反射去构造一个泛型数组,同时利用native函数,批量赋值元素至新数组中 */ public ArrayList(Collection<? extends E> c) { //把集合转化成Object[]数组 elementData = c.toArray(); //转化后的数组长度赋给当前ArrayList的size,并判断是否为0 if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class) // 若 c.toArray() 返回的数组类型不是Object[],则利用Arrays.copyOf(); 来构造一个大小为 size 的 Object[] 数组 elementData = Arrays.copyOf(elementData, size, Object[].class); } else { //当长度为0是用空数组进行替换 this.elementData = EMPTY_ELEMENTDATA; } }
方法分析:
1、add(E e)方法
0