注意:基于jdk1.8
1. ArrayList
1.1 ArrayList类结构
1.1.1 Cloneable接口
一个类要调用clone()
方法,就要实现Cloneable
接口并且重写Object
的clone()
方法,否则会报CloneNotSupportedException
异常,并且要在clone()
方法中调用了super.clone()
,这意味着无论clone
类的继承结构是什么样的,都调用了java.lang.Object
类的clone()
方法。
1.1.2 RandomAccess接口
实现了RandomAccess
接口则使用for
循环方法遍历,没实现则使用Iterator
方法遍历,我们知道ArrayList
实现了RandomAccess
接口,但是LinkedList
并没有实现这个接口,这是因为ArrayList
的for
循环速度较快,和LinkedList
用Iterator
速度更快。
1.1.3 Serializable接口
Serializable
是序列化接口,ArrayList
重写了readObject()
和writeObject()
方法
readObject()
即反序列化,writeObject()
即序列化
1.2 ArrayList属性
//初始容量为10
private static final int DEFAULT_CAPACITY = 10;
//指定该ArrayList容量为0时返回该空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//他与EMPTY_ELEMENTDATA区别是,EMPTY_ELEMENTDATA是在ArrayList容量为0时返回,后者默认返回
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//保存添加到ArryList中的元素
transient Object[] elementData;
//ArrayList实际大小
private int size;
1.3 构造方法
1.4 add方法
1.4.1 add(E e)
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
上面的方法实现了下面两个
- 确认list容量,尝试容量加1,看看有无必要
- 添加元素
随后调用
ensureExplicitCapacity(
)来确定明确的容量接下来看
grow()
函数总结:
首先去检查一下数组的容量是否足够,如果足够就直接添加,如果不够就
- 扩容到原来的1.5倍
- 第一次扩容后,如果容量还是小于
minCapacity
,就将容量扩充为minCapacity
。
1.4.2 add(int index, E element)
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1);
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
1.5 ArrayList总结
- ArrayList是基于
动态数组
实现的,在增删时候,需要数组的拷贝复制。
- ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍
- 删除元素时不会减少容量,若希望减少容量则调用trimToSize()
- 它不是线程安全的。它能存放null值。
2. Vector
- Vector是jdk1.2的类了,比较老旧的一个集合类。
- Vector底层也是数组,与ArrayList最大的区别就是:同步(线程安全)
- 如果想要ArrayList实现同步,可以使用Collections的方法:List list =
Collections.synchronizedList(new ArrayList(...));,就可以实现同步了 - ArrayList在底层数组不够用时在原来的基础上扩展0.5倍,Vector是扩展1倍。
3. LinkedList
3.1 LinkedList类结构图
- 没有实现
RandomAccess
接口,因为他用迭代器遍历更快 - LinkedList底层是双向链表
-
LinkedList
实现了Deque
接口,因此,我们可以操作LinkedList
像操作队列和栈一样
3.2 属性
size,头结点,尾结点
3.3 构造方法
3.4 add
头插和尾插