Array List
private static final int DEFAULT_CAPACITY = 10;//默认大小为10
protected transient int modCount = 0;//记录修改的次数的变量
//使用数组来存储数据
public ArrayList(Collection<? extends E> c) {//传入集合类型
Object[] a = c.toArray();//先转换为数组
if ((size = a.length) != 0) {//判断传入的集合长度
if (c.getClass() == ArrayList.class) {//类型相同,直接传
elementData = a;
} else {//复制
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {//返回一个空的
elementData = EMPTY_ELEMENTDATA;
}
}
//生长函数
private void grow(int minCapacity) {
int oldCapacity = elementData.length;//获取原来的数据长度
int newCapacity = oldCapacity + (oldCapacity >> 1);//将长度扩增到原来的1.5倍
if (newCapacity - minCapacity < 0)//扩增后的长度仍然不够用,就将使用传入长度扩增
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)//判断是否超过了最大的限制
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
Link List
//使用链表进行数据的存储
transient int size = 0; //初始长度
transient Node<E> first;//首节点
transient Node<E> last;//尾节点
private static class Node<E> {//使用双向链表
E item;//存的数据
Node<E> next;//后一个
Node<E> prev;//前一个
//一个完整的节点
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
//后插法的增加元素
void linkLast(E e) {
//先获取最后的指针last,然后让其指向给新节点指向前节点
//让本节点给last让其指向
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)//如果last为null,说明里面原本没有元素
first = newNode;//唯一的元素,frist也指向
else
l.next = newNode;//将前一个的节点的next指向新节点
size++;
modCount++;
}
//删除元素--让其无前后指针指向,被内存回收
private E unlinkFirst(Node<E> f) {
final E element = f.item;//先保存数据
final Node<E> next = f.next;//获取节点的next
f.item = null;
f.next = null; // help GC 将节点的数据和next置为null让GC回收
first = next;//将frist指向下一个节点
if (next == null)//判断是否是最后一个元素
last = null;
else
next.prev = null;
size--;//总数量减少
modCount++;//修改量+1
return element;//返回删除的数据
}
//可以实现栈的结构
//源码中使用前插法
public void push(E e) {
addFirst(e);
}
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
//我认为这里的设计很巧妙,声明私有变量存储size,避免了每次查询链表的长度的时候都要遍历
public int size() {
return size;
}
//删除的时候先判断是否为空,然后通过遍历找到元素
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {//链表的遍历
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
Vector
synchronized //关键字贯穿了这个类,这个类型是线程安全的
protected Object[] elementData;//使用的是数组存储数据
public Vector() {//默认的长度为10
this(10);
}
//可以指定初始的长度和我们的增长系数
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
//增长函数
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;//获取原本的长度
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
//如果初始化给定了增长长度,使用初始化长度增加,否则二倍增加
if (newCapacity - minCapacity < 0)//这里的判断和Arraylist相似
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
总结
ArrayList默认大小为10,增长倍数为1.5倍,使用数组来存储数据
LinkList初始长度为0,使用双向链表进行存储数据,能够作为栈来使用,使用前插法实现
Vector初始长度为10,可以设置增长长度,默认的增长长度为2倍,使用数组来存储,线程安全