对于开发人员来说,用的最多的就是数组,链表,Map和List,之前我写过一篇HashMap的源码解读,今天就来简单说说ArrayList的源码。java源码系列。
一.首先看看她的初始化方法:
第①种
public ArrayList() { //无参的构造器,初始值是一个默认的空 DEFAULTCAPACITY_EMPTY_ELEMENTDATA ={} this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}第②种
public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { //如果值不为空 // c.toArray 可能返回的不是 Object[] if (elementData.getClass() != Object[].class) // elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // 如果为空无赋值空对象 this.elementData = EMPTY_ELEMENTDATA; } }
第③种
public ArrayList(int initialCapacity) { //指定初始大小 if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; //初始化对象数组,指定数组的大小为初始值 } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { //若果initialCapcity<0要抛出异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
二. 添加:
public boolean add(E e) { ensureCapacityInternal(size + 1); // 判断是否需要扩容 elementData[size++] = e; //添加一个元素 return true; }
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //如果为空对象, minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //minCapacity为0和DEFULT_CAPACITY(10)取最大值为10 } ensureExplicitCapacity(minCapacity); //校验容量 }
private void ensureExplicitCapacity(int minCapacity) { modCount++; //修改的值加1 // overflow-conscious code if (minCapacity - elementData.length > 0) //如果容量大于数组的长度句需要扩容 grow(minCapacity); }
private void grow(int minCapacity) { //扩容 // overflow-conscious code int oldCapacity = elementData.length; //老表的大小 int newCapacity = oldCapacity + (oldCapacity >> 1); //扩容1.5倍 if (newCapacity - minCapacity < 0) //一般来说这里不会小于0 newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) //大于最大值,要进一步判断 newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); //用Arrays.copyOf赋值数组 }
private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow 多线程修改这个list的长度小于0,要报错 throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
到此,list的添加完毕,总结如下:
1.如果没有指定list的长度,初始一个空的数组
2.添加值的时候,list长度大于当前容量,就扩展1.5倍(默认长度是10),否则就正常添加
三. 获取值
public E get(int index) { rangeCheck(index); //校验一下索引值 return elementData(index); }
private void rangeCheck(int index) { //如果索引大于list的长度 抛出异常 if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
E elementData(int index) { //获取索引值 return (E) elementData[index]; }
四.删除值
public E remove(int index) { rangeCheck(index); //校验索引 modCount++; //修改记录数加1 E oldValue = elementData(index); //获取到索引的值 int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index,numMoved); //将获取的index位置值扣掉,后面的值,复制到index位置 elementData[--size] = null; // 将索引值赋值为空,便于gc return oldValue; }
public static native void arraycopy(Object src, int srcPos, //src 源数组 srcPos 原数组要赋值的起始位置 Object dest, int destPos, // dest 目标数组 destPost 目标数组放置的起始位置 int length); //lenth 复制的长度
到此,ArrayList增删查就完成了,不过里面有几点需要注意一下。
1.ArrayList初始化的时候,默认值是10,有可能就尽量执行list的大小,因为每次扩容都是1.5倍,长度越大,浪费越大。
2.ArrayList是线程不安全的,注意多线程问题。
本文深入解析了Java中ArrayList的工作原理,包括初始化、添加、获取和删除等操作的实现细节,并探讨了其内部扩容机制和线程安全性问题。
876

被折叠的 条评论
为什么被折叠?



