实现List接口的类
其中常用的有一个ArrayList和LinkList
1.ArrayList
ArrayList常用的方法
add(Object o)
get(int index)
remove(int index)
toArray();
不能将Object[]转换成为Arraylist[]
ArrayList的实现
任何一个集合中存放的不是对象本身,而是集合的引用
1.构造方法
这是ArrayList的一个构造方法,首先调用父类不带参数的构造方法
initialCapacitiy//这个值是传入构造方法的值,表示初始化的数组的长度的初始值
当这个值<0的时候抛出异常
this.elementData = new Object[initialCapacity];//这句代码表示在ArrayList的内部维护了
了一个初始值为initialCapacitiy的数组,类型为Object类型
这是默认不带参数的构造方法,对于不带参数的构造方法,会初始化一个EMPTY_ELEMENTDATA的数组,这是一个空数组
在旧版本的jdk中,会生成一个初始长度为10的数组
2.add方法
在add方法中调用了ensureCapacityInternal(int minCapatity)
在ensureCapacityInternal(int minCapatity)方法中elementData是ArrayList维护的一个数组
if (elementData == EMPTY_ELEMENTDATA) { //如果数组为空的时候
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//就为数组设定一个最小值DEFAULT_CAPACITY
DEFAULT_CAPACITY是一个常量,值为10
然后再调用 ensureExplicitCapacity(int minCapacity)
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0) //首先判断数组中的元素是否溢出
grow(minCapacity); //当继续往数组里面添加对象直到数组中的位置不够用的时候就会调用grow方法
}
在数组的容量不够的时候就会调用grow方法
在这里又调用grow方法
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //首先将数组原来的长度的值赋值给oldCapacity
int newCapacity = oldCapacity + (oldCapacity >> 1); //(oldCapacity >> 1)这个表示右移1位,用二进制来表示就是除以2,加上原来的
oldCapacity
//不难得出
newCapacity的值是
oldCapacity的值的1.5倍
//newCapacity可以理解为预期数组的新容量,minCapacity可以理解为刚刚好包含所有元素的最小容量
if (newCapacity - minCapacity < 0) //这里比较newCapacity的值和minCapacity的值
newCapacity = minCapacity; //如果预期容量比刚好包含所有元素的最小容量要小,预期容量就变成包含所有元素的最小容量
if (newCapacity - MAX_ARRAY_SIZE > 0) //接着比较newCapacity和MAX_ARRAY_SIZE
//MAX_ARRAY_SIZE的值是int类型所能够表示的最大的整数值-8,java中int能够表示的最大值是
2147483647
//所以MAX_ARRAY_SIZE的值是2147483639
newCapacity = hugeCapacity(minCapacity); //如果newCapacity 比 MAX_ARRAY_SIZE大,就是newCapacity的值大于
2147483639,就要执行容量溢出判断
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);//然后新建一个长度为newCapacity的数组u,并且将旧的elementData中原来的内容
} //复制到新的elementData中
容量溢出判断函数
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow //如果minCapacity的值小于0,就说明数组中可以容纳的元素的个数已经超过了int类型所能够表示的范围
//就是超过了
2147483647,为什么超过了会变成负数呢?因为在二进制中,最高位是符号位,当超过了
//2147483647的时候,最高位(也就是符号位)会变成1,所以变成了负数
throw new OutOfMemoryError(); //这时候就会抛出OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? //如果没有抛出这个错误,就会执行return语句,return语句的意思是
Integer.MAX_VALUE : //比较minCapacity 和 MAX_ARRAY_SIZE,如果是minCapacity比较大,就是所minCapacity比
2147483639
MAX_ARRAY_SIZE; //大,但是比
2147483647小,这时候就返回int类型所能够表示的最大值MAX_VALUE,如果minCapacity比较小
} //就返回MAX_ARRAY_SIZE,就是
2147483639
3.get()方法
首先执行rangeCheck(index)方法
这个方法用来检查传入的index有没有超出元素的个数,如果超过就抛出越界异常
如果没有超过,继续执行get方法,放回elementData数组的第index个元素
4.remove()方法
public E remove(int index) {
rangeCheck(index); //首先依然是检查需要remove的元素是否有越界
modCount++; //这里的modCount的作用是对arrayList的修改次数进行计数
E oldValue = elementData(index); //将被删除的元素赋值到oldValue中,以便返回
int numMoved = size - index - 1; //计算出需要从第几个元素开始移位
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, //这句代码是数组拷贝,实际上是移位操作,就是从elementData的第index+1的
numMoved); //位置上开始复制到elementData的index上
elementData[--size] = null; // clear to let GC do its work //数组的size数量-1,而且最后一个元素为空
return oldValue;
}
LinkList的实现
1.构造方法
LinkList的实质是一个双向链表,有一个内部类,相当于节点
2.add方法
在add方法中调用了linkLast方法
void linkLast(E e) {
final Node<E> l = last; //将最后一个节点赋给l,这个是英文的“L”的小写不是1
final Node<E> newNode = new Node<>(l, e, null); //新建一个节点,新建节点的头指针为l,就是原来链表的最后一个节点
last = newNode; //将最后一个节点改成新的节点
if (l == null) //如果原来的链表是空链表,那么第一个节点就是新的节点
first = newNode;
else
l.next = newNode; //否则,原来旧的节点的最后一个节点的下一个节点就是新的节点
size++;
modCount++;
}