ArrayList部分源码介绍(jdk 8)

 1.简单介绍

        定义

               ArrayList是一种支持索引插入有序允许集合元素重复单列集合(非线程安全),它实现了三个标志性接口(接口中什么也没有,只是单纯定义,用于标识) Serializable,Cloneable, RandomAccess

/*
 实现这个接口的类的对象可以被jdk进行序列化,反序列化
 序列化: 将java中的类或者对象转换成字节流,而字节就是二进制,计算机只认识二进制,将java对象转换成 
     字节流就可以实现网络传递,或者保存在文件中等用途
 反序列化:将java对象转换成的字节数据转换成原来的对象

*/
public interface Serializable {
}

/*
 实现这个接口的类可以被克隆,克隆又分为深克隆,浅克隆,这里不做讲解。
*/
public interface Cloneable {
}

/*
 实现这个接口的类的对象支持随机访问,随机访问其实就是根据索引查数据,类似数组
*/
public interface RandomAccess {
}

2.原理

       基本流程

                1.ArrayList底层是用数组存放数据的,不过是动态数组(容量不够时自动扩容)

                2.调用无参构造方法时,会构建一个容量为0数组,是懒加载的,只有在实际用到这个集合时对数组进行真正的初始化,第一次新增会初始化一个容量为10 的数组

                3.每次进行增加,插入等新增操作,会先判断数组容量,不够时扩容1.5倍。

       重要属性
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{

    /*
       java对象序列化后保存在文件,或者其他地方时,
       如果被修改了再反序列化成对象时,jvm会认为这个对象不是原来的对象,
       加上唯一的版本号,也就是这个属性后,jvm会根据这个属性来判断是不是原来的对象。
    */
    private static final long serialVersionUID = 8683452581122892189L;

   
    /*
        调用无参构造方法时,数组的默认容量
    */
    private static final int DEFAULT_CAPACITY = 10;

 
    /*
        调用有参构造方法时,传入的容量为0时,数组的默认初始化数组就是这个属性的值
    */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /*
        调用无参构造方法时,数组的默认初始化数组就是这个属性的值
    */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};


    /*
        ArrayList真正存放数据的数组
    */
    transient Object[] elementData;

    /*
        ArrayList实际的数据数量
    */
    private int size;
}
       初始化

                

    /*
         无参构造,用到上面介绍的几个属性,这里只是验证一下
   */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }


    /*
         有参构造,用到上面介绍的几个属性,这里只是验证一下
    */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            如果传入的容量不为0,则直接进行初始化,不会调用到上面定义的常量。
            this.elementData = new Object[initialCapacity];

        } else if (initialCapacity == 0) {

            this.elementData = EMPTY_ELEMENTDATA;

        } else {
            //这里是传入的容量为负数,直接抛出异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
   
        add()源码

                这里只介绍add()的源码,本文主要是介绍ArrayList的初始化流程。

    /*
        这里的size属性是上面介绍的属性之一,也就是数组的实际容量
        上面也介绍了,每次新增数据时,会先判断数组需不需要扩容
    */
    public Boolean add(E e) {
    /*
        这个就是判断数组是不是需要扩容,按理说应该直接传入size,
        但这里传入了size+1,可以理解成为了方便运算
    */
        ensureCapacityInternal(size + 1);

     //无论上面那个方法结果是什么,执行到这里数组的容量一定是够用的
        elementData[size++] = e;

        return true;
    }


    //这个方法是上面调用的方法,它又调用了两个方法,
//但你只需知道它是判断是否需要扩容,如果需要就进行数组扩容操作的方法就行
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }


    // 这个方法是用来计算数据的容量的
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        /*这里判断如果elementData的地址是上面介绍的那个属性,
也就是通过无参构造实例化的,就说明它是第一次新增操作,此时数组的容量为0,
所以这里一定是DEFAULT_CAPACITY大的,也就是10,会创建一个长度为10的数组 */
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //如果不是就返回minCapacity,也就是数据的长度 + 1,
//注意是此时数组里数据的数量 + 1
        return minCapacity;
    }


   
    //这个是进一步判断是否需要扩容的操作
    private void ensureExplicitCapacity(int minCapacity) {
        //这里是记录集合的修改次数,不用关心
        modCount++;
 
        //这里如果 数组的数据数量 + 1 - 数组的长度 > 0 ,说明需要扩容
        if (minCapacity - elementData.length > 0)
            //扩容操作
            grow(minCapacity);
    }


    private void grow(int minCapacity) {
        // 实际数组的长度
        int oldCapacity = elementData.length;
        // 对实际数组长度进行右移1位,也就除以2的1次方,再加上 原来的长度,也就是所谓的 1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);

        //这里判断扩容后的数组长度是不是能满足要求,不满足则用实际数据长度 + 1作为新容量
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;

        //这个就是数组的长度已经比int的最大数 -8 还大,这里一般不会发生,故不作讲解
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);

        // 重新创建一个扩容后的数组,并将原数组的数据复制过去
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值