ArrayList内部实现原理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList内部实现原理相关的知识,希望对你有一定的参考价值。

ArrayList内部实现原理

首先,我们new一个对象list集合

	List<String> list = new ArrayList<>();

我们知道对象的创建离不开构造方法,因此我们查看ArrayList源码的时候先看其构造方法

	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	transient Object[] elementData; // non-private to simplify nested class access
	
	public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

通过源码我们发现在new ArrayList<>()的时候,其实质是获得一个Object[]数组;
因此ArrayList的本质就是一个数组
然后我们向元素中添加一个对象通过add()方法,并查看add的源码

	list.add("123");
	private int size;

 	public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

在add方法中调用了一个方法ensureCapacityInternal()用来初始化容量
然后向数组的末尾添加了一个元素

接下来我们来看看这个ensureCapacityInternal()方法的内部是如何实现的

	private static final int DEFAULT_CAPACITY = 10;

	private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

很显然在ArrayList被创建的时候执行了this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;,因此if语句是成立的,我们知道当我们第一次执行add("123")的时候size=0,因此该方法的参数是1。所以minCapacity=10
然后我们看ensureExplicitCapacity(minCapacity);这个方法的内部。

	protected transient int modCount = 0;

	private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

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

因为elementData是一个null的对象数组,所以elementData.length=0,if条件成立执行grow(minCapacity)

	 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

	private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        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:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

因为minCapacity=0,所以newCapacity=0,导致if(newCapacity - minCapacity<0)成立,结果newCapacity = minCapacity;等于10;
MAX_ARRAY_SIZE= Integer.MAX_VALUE - 8;可以认为MAX_ARRAY_SIZE是一个无穷大的数,因此if (newCapacity - MAX_ARRAY_SIZE > 0)语句不成立,elementData = Arrays.copyOf(elementData, newCapacity);拷贝原数组到新数组,新数组长度为10;

当我们继续添加直到ArrayListsize=10,我们继续add第11个对象的时候if (minCapacity - elementData.length > 0)成立,

 		int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);

因此,当ArrayList容量存满的时候,会扩容为原来的3/2倍

通过内部原理可知,对于ArrayList的每次操作,当需要扩容的时候,每次扩容为当前长度的1.5倍,但是每次操作集合都需要进行数组的拷贝,此过程消耗资源,所以如果对于经常对集合进行添加删除操作的时候,不建议使用ArrayList

技术分享

ArrayList内部原理







以上是关于ArrayList内部实现原理的主要内容,如果未能解决你的问题,请参考以下文章

数据结构ArrayList原理及实现学习总结

深入Java集合:ArrayList实现原理

LinkedList内部实现原理

JDK1.8中ArrayList的实现原理及源码分析

Java中Arraylist源码分析

ArrayList底层原理