数据存储核心之ArrayList源码探究

ArrayList底层是数组队列,相当是动态数组,可以理解为是一种可变长度的基于数组实现的集合类。

ArrayList用法

一、ArrayList类图结构

在这里插入图片描述

相关的接口抽象类的介绍

类名说明
AbstractCollection实现了Collection中大量的函数,除了特定的几个函数iterator()和size()之外的函数
AbstractList该接口继承于AbstractCollection,并且实现List接口的抽象类。它实现了List中除size()、get(int location)之外的函数。AbstractList的主要作用:它实现了List接口中的大部分函数和AbstractCollection相比,AbstractList抽象类中,实现了iterator()接口
RandomAccessRandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问
List有序队列接口,提供了一些通过下标访问元素的函数List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1

二、ArrayList源码

 /**
     * Default initial capacity.
     * 默认数组的长度,即初始容量为10
     */
    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

    /**
     * The size of the ArrayList (the number of elements it contains).
     *集合中元素的个数
     * @serial
     */
    private int size;

三、初始操作之无参构造

ArrayList list = new ArrayList();

        源码分析

 	/**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

        elementData=null;无参构造去并不会真实的创建数组,数组会在add方法中去创建,有助于性能的提升,懒加载的方式。

四、初始操作之有参构造

在这里插入图片描述
        源码分析

/**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
        //初始长度大于0 就创建一个指定大小的数组
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
        //{}数组赋值给 this.elementData
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

五、add方法源码分析

ArrayList list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);

        初始无参构造器

        第一次添加

 /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
   		//确定容量 动态扩容 size初始值 0 (原因在下一源码)
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //将要添加的元素 添加到数组中 elementData[0] = 1 --> size = 1
        elementData[size++] = e;
        return true;
    }
/**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;
private void ensureCapacityInternal(int minCapacity) {
		// 10
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
 /**
     * elementData {}
     * minCapacity 1
     */
  private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        // 10 1 return 10
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //1
        return minCapacity;
    }
private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//增长 操作次数

        // overflow-conscious code
        //minCapacity 10 - 0
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

        进入grow方法

/**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {//10
        // overflow-conscious code
        int oldCapacity = elementData.length;//0
        //newCapacity = 0
        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:
        // {} {,,,,,,,,,} 返回一个新的数组 长度为10
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
/**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
     //调用MAX_ARRAY_SIZE不执行 
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

        第二次添加

elementData = {1,,,,,,,,,};
size = 1
 public boolean add(E e) {
   		// 2
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e; //elementData[1] = 2   size = 2
        return true;
    }
 private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        // 2
        return minCapacity;
    }
private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//增长 操作次数

        // overflow-conscious code
        //2-10
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

        第十一次添加

elementData = {1,2,3,4,5,6,7,8,9,10};
size = 10
 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e; //elementData[1] = 2   size = 2
        return true;
    }
private void ensureCapacityInternal(int minCapacity) {
		// ensureExplicitCapacity(11)
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        //11-10
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
private void grow(int minCapacity) {//1
        // oldCapacity  10
        int oldCapacity = elementData.length;//0
        //newCapacity = 15 newCapacity 是 oldCapacity 的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:
        // {1,2,3,4,5,6,7,8,9,10} 复制到新的数组{1,2,3,4,5,6,7,8,9,10,,,,,}
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

六、get方法源码分析

/**
     * Returns the element at the specified position in this list.
     *
     * @param  index index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
    	//检查下标是否合法
        rangeCheck(index);
		//通过下标获取数组对应的元素
        return elementData(index);
    }

七、set方法源码分析

 public E set(int index, E element) {
        rangeCheck(index);//检查下标
		//获取下标原来的值
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

八、remove方法源码分析

 /**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).
     *
     * @param index the index of the element to be removed
     * @return the element that was removed from the list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E remove(int index) {
        rangeCheck(index);//检查下标

        modCount++;//记录修改次数
        E oldValue = elementData(index);//获取原来的值
		//获取要移动元素的个数 {1,2,3,4,5,6,7,8,9} // 3   size=9   index=3
		//{1,2,3,5,6,7,8,9,null}
        int numMoved = size - index - 1;// 5
        if (numMoved > 0)
        //源数组  开始下标  目标数组  开始下标  长度
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
		//删除的节点对应的信息
        return oldValue;
    }

九、ArrayList类总结

ArrayList类
动态数组结构
查询快,添加/删除慢
没有提供对第一个元素和最后一个的操作
适合大量查询操作
初始容量为10
每次扩容后的大小为之前的1.5倍
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值