Java语言之ArrayList源码分析(jdk1.8)

1、ArrayList特点

        ArrayList在数据结构中可以类比为一个数组,然而又与数组差别很大,最大的差别在ArrayList没有容量的限制(动态数组)。而数组在申明时就必须给定容量,且在接下来的使用中存放的数据个数不可以超过容量。其实ArrayList的底层实现也是一个数组,只不过他在实现的时候做了一些优化,从而突破List容量限制的功能

2、ArrayList源码分析

        2、1数据结构与储存

            
             //ArrayList默认的大小,大小为10
             private static final int DEFAULT_CAPACITY = 10;

             private static final Object[] EMPTY_ELEMENTDATA = {};

             private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
            //elementData为一个数组,用于存放ArrayList中的元素   
              transient Object[] elementData; // non-private to simplify nested class access
            //当前数组elementData的大小  
             private int size;

         2、2核心方法分析

               2、2、1构造函数分析

                    无参构造函数
         /**
             * Constructs an empty list with an initial capacity of ten.
         */
	 //无参构造函数,将当前当前一个为空的DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋值给elementData;
	 public ArrayList() {
		this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
	 }
                   带容量参数的构造函数
        public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
			
			//当initialCapacity参数合法时申请一个长度为initialCapacity的数组
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
			
			//为空
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
			//参数非法
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
	}
                    带集合的构造函数
                    
        /*
		1、将集合转换为数组,并赋值给elementData
		2、判断赋值后的elementData的长度
			如果为0则进行以上函数initialCapacity为0的相同操作
			如果不为0则调用数组的拷贝方法,将elementData重新分配内存单元,并进行赋值(类似C++的深拷贝)
	*/
	public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
        }

              2、2、2重要方法分析

                 add方法:
                 add方法中最核心的为:
                    elementData = Arrays.copyOf(elementData, newCapacity);
                 //将elementData中的数值拷贝到长度为newCapacity的elementData(覆盖)中
        /*
		1、先确保当前的elementData有足够的空间去存放指定的泛型数据
		2、在确保已经有足够的空间的条件下进行直接赋值操作
	*/
	 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
	
	private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
	
	//计算elementData的容量
	 private static int calculateCapacity(Object[] elementData, int minCapacity) {
		 //当数组还没有分配内存空间的时候,返回默认设置的容量(默认容量为10)与指定容量的较大值
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
		
		//如果不为空,返回minCapacity
        return minCapacity;
     }
	 
	  private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
		//判断数组是否要进行自增长,当当前的容量超过最小容量时,数组要进行自增长
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
	
	//自增长函数,将当前elementData的容量扩大1.5倍
	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);
    }
         get方法
    //get方法
	 public E get(int index) {
	 //用于检测index下标是否已经越界
        rangeCheck(index);

        return elementData(index);
    }
        set方法
        
    //set方法
	public E set(int index, E element) {
		 //用于检测index下标是否已经越界
        rangeCheck(index);

		//保存旧值并设置新值
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
未完待续............
附:限于编者水平与能力,欢迎广大读者批评指正

            


 
  






猜你喜欢

转载自blog.csdn.net/qq_36441169/article/details/80820345