ArrayList源码

本篇文章讨论以下几个问题

目录

本篇文章讨论以下几个问题

1.ArrayList的初始化

        三种构造函数初始化过程

2.动态扩容的过程

        如何扩展集合长度

        加载因子的大小问题

3.线程安全问题

        什么情况下会出现线程安全问题

        如何解决集合中的线程安全


ArrayList的初始化

1.无参构造 - ArrayList()

ArrayList arrayList = new ArrayList();

//ArrayList存放数据的数组 
transient Object[] elementData; //空数组

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 

//无参构造
public ArrayList() {        
  this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;  //集合初始化一个空数组 
}

        构造函数有两个变量,这里我就可以得出:ArrayList的底层是由数组实现的,且我们没有给初始长度的时候默认给的是一个空数组;[空的怎么存数据??试试给个初始大小]

2.有参构造 - ArrayList(1)

ArrayList arrayList = new ArrayList(1); 

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);
        }
	}

还是能传0的啊?add()加个数据试试,看看什么情况?



//新增数据 
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!! ??? 这干嘛的???
        elementData[size++] = e;
        return true;
    }

private void ensureCapacityInternal(int minCapacity) { 
    //这里会有判断的啊,如果是空的就从 DEFAULT_CAPACITY, minCapacity 选个大的。
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        
		//private static final int DEFAULT_CAPACITY = 10;  这里才给个大小为10的啊。
        
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

关于初始数组为0,为啥也能添加的数据的过程已经get到了,下一个构造函数看看。

3.集合类参数 - ArrayList(Collection<? extends E> c)

参数说明:

        Collection:集合的子类可以当做参数

        <? extends E> :泛型,必须是E的子类

 public ArrayList(Collection<? extends E> c) {
     
        elementData = c.toArray();//将参数c(c是个数组)转换成数组
     
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)??这什么意思??
            //c.toArray() 有坑??
            if (elementData.getClass() != Object[].class) 
                //当真的出现 c.toArray() ,jdk 也做了处理方案。拷贝复制!!
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA; //这不就是相当于无参构造了嘛,弄了个寂寞
        }
    }

小小脑袋,大大的问号。不禁感慨自己太菜!!!

c.toArray()会有什么坑????[谁能告诉我?]

elementData.getClass()与Object[].class ,class 比较又是个什么玩意?(* ̄︶ ̄)

搁置疑问,接着看扩容吧... ...


动态扩容的过程

要想动态的扩容,肯定是在添加数据的时候。集合自己判断要不要扩容,去看看add咋搞的。

扩容吧小宝贝 - add(E e)

ensureCapacityInternal(size + 1) 似曾相识啊,初始化 为0的时候为啥能添加数据,刚刚看过。

private int size;//记录集合的实际存放的元素个数;

public boolean add(E e) {
    //size+1 的目的:因为是添加元素,所以就要把当前数组的实际长度增加1           
    //看看是否超出了集合的当前容量
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    
    //当前存放数组元素个数+1
    elementData[size++] = e;
    return true;
}

来再看下 ensureCapacityInternal(int minCapacity)

private static final int DEFAULT_CAPACITY = 10;//默认容量10;

private void ensureCapacityInternal(int minCapacity) {
    //如果当前数组是一个空数组的话,就取两个数的最大值。这里取得是容量10,当第一次使用add方法
    //才去给数组一个固定的容量!可能是为了节约内存吧。脑壳疼。
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    //咳咳,去下面看这个方法的讲解
    ensureExplicitCapacity(minCapacity);
}

老母猪戴胸罩,一套又一套 。来看这个tao~ ensureExplicitCapacity(minCapacity);

//来了,宝?
private void ensureExplicitCapacity(int minCapacity) {
    //这个东西是记录,修改次数的。咱们这次就不管这个东西了
    modCount++;

    //不是从一开始就传进来一个size+1么?到这里才用上,到底扩不扩容就看这次的比较了
    //当前实际大小+1之后大于了数组定义的长度,那肯定不行啊。妥妥的扩容
    if (minCapacity - elementData.length > 0)
        //下面去看扩容解释 
        grow(minCapacity);
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值