ArrayList关键源码分析

ArrayList源码分析

1.数据结构:
	实现了List接口。
	根据语义可知是由数组线性表;有序。
	非线程安全,没有加锁,没有CAS处理。
	
2.全局变量
	//1.默认长度
	private static final int DEFAULT_CAPACITY = 10;
	//2.给空实例用的数组
	private static final Object[] EMPTY_ELEMENTDATA = {};
	//3.这里参照doc注释。用于默认大小的空实例的共享空数组实例。我们将其与EMPTY_ELEMENTDATA区分开来,以了解何时应该充气多少
		添加第一个元素
	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	//4.实际存储在这个elementData中,但是不序列化这个数组
	transient Object[] elementData; 
	//5.数组大小
	private int size;
	
3.构造方法
	(1)public ArrayList()无参构造方法:
		//初始化了一个对象数组  
		this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
	(2)public ArrayList(int initialCapacity)	参数为int类型的一个容器初始值
		//指定了对象数组的大小
		if (initialCapacity > 0) {
			this.elementData = new Object[initialCapacity];
		} else if (initialCapacity == 0) {
			this.elementData = EMPTY_ELEMENTDATA;
		} else {
			throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
		}
	(3)public ArrayList(Collection<? extends E> c) 参数为集合类泛型
		//1.将集合转化为数组
		elementData = c.toArray();
		//2.判断数组长度
		if ((size = elementData.length) != 0) {
			//3.这里判断了一下不是数组的情况,其实这里是指第1步中使用的集合类转化数组没有成功的情况下
			// 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;
		}
		
4.核心方法 add()
	(1)public boolean add(E e){
			//具体实现
			ensureCapacityInternal(size + 1);  // Increments modCount!!
			//将该元素插入数组
			elementData[size++] = e;
			return true;
		}
		
		分析ensureCapacityInternal(int minCapacity)方法。
			private void ensureCapacityInternal(int minCapacity) {
				//如果是空的,size大小为默认10
				if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
					minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
				}
				ensureExplicitCapacity(minCapacity);
			}
			
		分析ensureExplicitCapacity(int minCapacity)方法。
		   private void ensureExplicitCapacity(int minCapacity) {
				//1.父类中的一个全局变量
				modCount++;
				if (minCapacity - elementData.length > 0)
					//2.核心方法(扩容)
					grow(minCapacity);
			}
			
		分析grow(int minCapacity) 方法,这里就是扩容。
			private void grow(int minCapacity) {
				//1.获取未加入新元素前数组长度
				int oldCapacity = elementData.length;
				//2.新的容器大小=老的容器大小+老的容器大小/2,即扩容
				int newCapacity = oldCapacity + (oldCapacity >> 1);
				//3.如果新的容器大小-先前容器的大小<0,则还使用之前的大小;
				if (newCapacity - minCapacity < 0)
					newCapacity = minCapacity;
				//4.如果新的容器大小大于最大整数-8,则最大为最大整数。
				if (newCapacity - MAX_ARRAY_SIZE > 0)
					newCapacity = hugeCapacity(minCapacity);
				//5.按照新生产的容器拷贝数据
				elementData = Arrays.copyOf(elementData, newCapacity);
			}
	(2)public void add(int index, E element) {
			//1.校验Index,不能大于size
			rangeCheckForAdd(index);
			//2.扩容
			ensureCapacityInternal(size + 1);  // Increments modCount!!
			//3.复制 把当前数组从第index元素起复制到 新的数组的index+1的位置,复制长度为数组长度-index(native方法)
			//arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
			System.arraycopy(elementData, index, elementData, index + 1,
							 size - index);
			//4.在数组index位置上赋值
			elementData[index] = element;
			size++;
		}	
		
	(3)由(1)可知末尾插入一个元素时间复杂度为O(1),由(2)可知中间插入一个元素的时间复杂度为O(n)。
	
5.核心方法get() 根据代码可知其查找元素的时间复杂度为O(1)
		public E get(int index) {
			//1.校验Index,不能大于size
			rangeCheck(index);
			//2.获取元素
			return elementData(index);
		}
		//根据下标直接找到
		E elementData(int index) {
			return (E) elementData[index];
		}

6.核心方法remov()
	(1)返回删除结果
		public boolean remove(Object o) {
			//1.当传入的对象为空时,遍历然后移除
			if (o == null) {
				for (int index = 0; index < size; index++)
					if (elementData[index] == null) {
						fastRemove(index);
						return true;
					}
			} else {
				for (int index = 0; index < size; index++)
					if (o.equals(elementData[index])) {
						fastRemove(index);
						return true;
					}
			}
			return false;
		}
		
		private void fastRemove(int index) {
			//1.modCount用于记录,当前集合类操作次数,在多线程情况下,发生改变时,根据内部方法调用,抛出异常
				在这些线程不安全的集合中,在某些方法中,初始化迭代器时会给这个modCount赋值,如果在遍历的过程中,
				一旦发现这个对象的modCount和迭代器存储的modCount不一样,就会报错。
			modCount++;
			int numMoved = size - index - 1;
			if (numMoved > 0)
				//2.复制要移动的数组
				System.arraycopy(elementData, index+1, elementData, index,
								 numMoved);
			elementData[--size] = null;
		}
	(2)返回了删除元素
		public E remove(int index) {
			rangeCheck(index);

			modCount++;
			E oldValue = elementData(index);

			int numMoved = size - index - 1;
			if (numMoved > 0)
				System.arraycopy(elementData, index+1, elementData, index,
								 numMoved);
			elementData[--size] = null; // clear to let GC do its work

			return oldValue;
		}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值