Array与ArrayList

目录

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

原文地址:https://www.cnblogs.com/youngao/p/12010771.html