ArrayList
1.构造函数
1.1无参构造函数:
//无参,构造一个初始容量为10的空列表
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
给出默认值为空,初始容量为10的空列表(调用add时候才能体现)
1.2给了初始容量的构造
//initialCapacity 初始容量
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);
}
}
直接给了初始容量initialCapacity:
大于0:将带有固定容量的数组赋给该数组集合
等于0:将{}赋给集合
小于0:抛出异常
1.3构造一个包含指定元素的列表
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray(); //把集合转换为Object[]数组(来自于Collection)
if ((size = elementData.length) != 0) { //把数组长度赋给当前的ArrayList集合的size,并判断是否为0
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class) //toArray返回的不一定时Object类型,得重新转换为Object类型
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA; //如果为0:将element替换为空数组
}
}
2.增add()
2.1add(E e)
public boolean add(E e) { //boolean型
//1.加入元素前,检查数组容量是否足够
ensureCapacityInternal(size + 1); // Increments modCount!!
//首先会调用 ensureCapacityInternal(size + 1),其作用为保证数组的容量始终够用,否则就扩容
//得到确切容量值
elementData[size++] = e; //在size后添加元素
return true; //添加成功
}
1.加入元素之前,检查数组容量是否足够
2.首先会调用 ensureCapacityInternal(size + 1),其作用为保证数组的容量始终够用,其中 size是elementData数组中元组的个数,初始为0
3.如果添加元素后大于当前数组长度,调用扩容函数grow(minCapacity)
4.扩容函数会在下面详细说明
2.2add(int index,E elsement)
public void add(int index, E element) { //void
rangeCheckForAdd(index); //index > size || index < 0
//检查下标值是否在数组容量范围
ensureCapacityInternal(size + 1); // Increments modCount!!
//得到确切容量值
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//将elementData从索引为index的元素开始,复制到数组elementData里的索引为index+1的位置,复制元素为size-index个
//总之就是将elementData插入index位置,之后的元素往后移一位
elementData[index] = element;
size++; //计数
}
3.扩容函数grow(int minCapacity)
private void grow(int minCapacity) { //容量要保证能装下mincapacity所指定的容量大小
// overflow-conscious code
int oldCapacity = elementData.length; //把数组的长度赋给oldCapacity
int newCapacity = oldCapacity + (oldCapacity >> 1); //加上自己本身一半
//新的数组容量=老的数组长度的1.5倍。
if (newCapacity - minCapacity < 0) //如果新的数组容量newCapacity小于传入的参数要求的最小容量minCapacity
newCapacity = minCapacity;//那么新的数组容量以传入的容量参数为准,够用就行。
if (newCapacity - MAX_ARRAY_SIZE > 0) //大于2^31-1-8时:
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win: //自己理解为很接近最大值,这样也可以
elementData = Arrays.copyOf(elementData, newCapacity); //最后,把旧数组放进扩容后的数组
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE : //如果还大的话就只能取2^31-1了
MAX_ARRAY_SIZE; //否则
}
先将容量扩充至当前容量的1.5倍,若还不够,则将容量扩充至当前需要的数量,再不够就扩容到最大
4.查get(int)
public E get(int index) {
rangeCheck(index);
//范围检查,注意,这里是index不能等于size,添加函数可以等于;还有一般也没有说取负数个的,所以也没有负数限制了吧
return elementData(index); //返回得到index位置的元素值
}
5.改set(int E)
public E set(int index, E element) {
rangeCheck(index); //同样是范围检查,其实看到上面就在想,为啥不加一个>=0的范围呢,否则小于0时 最后返回的是啥呢
E oldValue = elementData(index); //存放原来位置上的元素
elementData[index] = element; //给该位置赋新值
return oldValue; //返回原来的元素值
}
6.删
6.1remove(int)
public E remove(int index) {
rangeCheck(index); //index >= size
modCount++; //记录更改次数
E oldValue = elementData(index); //存放元素
int numMoved = size - index - 1; //移除元素后,其它元素需要移动numMoved个
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//相当于数组复制,将elementData从索引为index+1位置复制到数组elementData索引为index位置,复制元素为size-index-1个
elementData[--size] = null; // clear to let GC do its work
//先给最末尾元素赋空值,然后让GC来清理
return oldValue; //返回原来的值
}
6.2remove(Object) (boolean类型)
和第一个删除函数差不多,找到相同的值然后调用了fastRemove函数,
里面最主要的还是包含了arraycopy函数,进行数组移动复制。
需要注意的是!!!:当对象为null时,不能调用equal进行比较,需要用==比较,null和其他object类不是相同对象
,==比较的时引用,而equal比较的是两个对象
采用什么数据结构?
数组
如何实现的?为什么这么实现?
线程是否安全?
线程不安全
说一下工作原理?
说一下每个函数的执行过程?
与其他数据结构的区别?
个人源码分析,有错勿怪,指出虚心改正