ArrayList集合初探

集合

在这里插入图片描述

List

ArrayList

- ArrayList 初始化底层
  • ArrayList 无参构造方法
   /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;


	/**
     * 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关键字只能修饰变量,而不能修饰方法和类。
	* 一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
	*/
    transient Object[] elementData; // non-private to simplify nested class access


	/**
     * 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 = {};


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

elementData

是一个存储 ArrayList 的数组缓存区,ArrayList的容量就是该数组缓存区长度。

当添加第一个元素时,任何具有 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空 ArrayList 都将扩展为 DEFAULT_CAPACITY

  • ArrayList 有参构造方法
    /**
     * 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) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

ArrayList 无参构造方法中,会初始化一个默认空的数组 DEFAULTCAPACITY_EMPTY_ELEMENTDATA

ArrayList 有参构造方法中,会更具形参 initialCapacity 分配一个指定容量大小的数组

- ArrayList 添加元素的底层实现
  • ArrayList 的add方法
    /**
     * 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) {
        //内部容量更新
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        
        elementData[size++] = e;
        return true;
    }


    private void ensureCapacityInternal(int minCapacity) {
        //最小的当期容量与原有数组容量对比 
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }


    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //判断原有元素集合 elementData 是否是之前为指定容量的无参初始化的 数组
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //如果当前超过当前数组默认容量 10 则返回当前的扩容后的空间
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //返回当前最新的扩容后的空间
        return minCapacity;
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            //扩容
            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:
        
        //完成数组的扩容copyOf扩容
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
======================================================================================================
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    /**
     * A constant holding the maximum value an {@code int} can
     * have, 2<sup>31</sup>-1.
     */
    @Native public static final int   MAX_VALUE = 0x7fffffff;
=====================================================================================================
- ArrayList 获取元素的底层实现
  • ArrayList 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);
    }

    /**
     * Checks if the given index is in range.  If not, throws an appropriate
     * runtime exception.  This method does *not* check if the index is
     * negative: It is always used immediately prior to an array access,
     * which throws an ArrayIndexOutOfBoundsException if index is negative.
     */
    private void rangeCheck(int index) {
        //检查获取的元素下标是否越界
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }


    @SuppressWarnings("unchecked")
    E elementData(int index) {
        //之间根据数组的下标查找元素
        return (E) elementData[index];
    }
- ArrayList 更新元素的底层实现
  • ArrayList set方法
    /**
     * Replaces the element at the specified position in this list with
     * the specified element.
     *
     * @param index index of the element to replace
     * @param element element to be stored at the specified position
     * @return the element previously at the specified position
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E set(int index, E element) {
        //访问元素下标越界检查
        rangeCheck(index);
        
        //返回修改之前的元素
        E oldValue = elementData(index);
        //之间通过数组索引修改元素
        elementData[index] = element;
        return oldValue;
    }
* ArrayList 总结

初始化:

  1. 当通过无参构造创建 ArrayList 对象的时候

    ArrayList 的底层会 默认一个已经在对象内部存在的空 Object 数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA(该数组是为指定初始默认大小的),交给与当前对象的数组缓存区 this.elementData

  2. 通过有参构造器创建 ArrayList 对象的时候

    ArrayList 的底层会 通过形参参数创建一个新的 Object 空数组,并初始化数组长度为形参参数,同时将该 Object 数组交给当前

    对象的数组缓存区 this.elementData

  3. 区别:

    1. 无参直接使用内部已经存在的空数组,有参会重新创建新的空数组
    2. 无参的空数组的长度为指定(在第一次调用put方法时会指定),有参的空数组的长度在创建时就已经指定(长度为形参长度)

元素的添加更新:

  1. 添加元素:

    1. 添加元素时会调用 ensureCapacityInternal,将当前的元素个数记录值 size +1,作为 ensureCapacityInternal 最小容量的中间变量 minCapacity
    2. calculateCapacity 方法中判断当前的对象中原有的 elementData 对象是否与初始化时的分配的 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 一致
      1. 如果相同(调用无参构造创建的ArrayrList对象),就直接返回当前已经存入的元素个数的最小容量(minCapacity)与 默认数组大小(DEFAULT_CAPACITY=10)中的最大值
      2. 如果不一致(调用有参构造创建的ArrayrList对象),返回当前最小容量 minCapacity
    3. 此时调用 grow 方法开始对数组扩容,这里对于无参的构造对象创建的 ArrayList 就会第一次初始化数组长度(length 10)
    4. grow 方法中,会先有一个有一个旧容量 oldCapacity,该容量来自于 elementData.length , newCapacity为旧容量的 1.5 倍(newCapacity = oldCapacity + (oldCapacity >> 1)
    5. 然后利用 Arrays.copyOf(elementData, newCapacity) 实现数组拷贝扩容
  2. 获取元素

    1. 判断索引下标是否越界,越界抛出异常,否则直接通过数组的下标索引获取元素
  3. 修改元素

    1. 直接通过索引的下标返回被修改的值,通过索引对元素修改
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值