1.ArrayList
(1). 特点 :
- 实现了List接口,存储有序的,可重复的数据.
- 底层使用Object[]数组存储.
- 线程不安全.(底层方法未用synchronized修饰.)
(2). 版本解析 :
<i> : JDK7版本
ArrayList<String> list =new ArrayList<>();
//底层会初始化数组,直接new了一个长度为10的数组
Object[] elementData =new Object[10];
list.add("AA")//elementData[0] ="AA";
list.add("BB")//elementData[1] ="BB";
......
当添加第11个元素时,底层的elementData数组已满,则需要扩容.扩容为原来数组长度的1.5倍.并将原来的数组的内容copy到新创建的数组中.
<ii> JDK8版本
ArrayList<String> list =new ArrayList<>();
//底层也会初始化数组,但该数组的长度为0
Object[] elementData =new Object[]{};
list.add("AA");//首次添加元素时,会初始化数组 : elementData =new Object[10];并elementData[0] ="AA";
list.add("BB");//elementData[1] ="BB".
当添加到11个元素时,底层数组已满,需要数组扩容,同样扩容至原来数组长度的1.5倍.并将原来数组的内容copy到新new出来的数组中.
小结 :
JDK7版本有点类似于饿汉式,一上来直接new长度为10的数组.
JDK8版本有点类似于懒汉式,创建ArrayList对象时new了一个长度为0的数组,当需要添加元素时,才new一个长度为10的数组.
2.Vector(JDK8版本)
Vector<String> vector =new Vector<>();
//底层初始化数组,长度为10;
Object[] elementData =new Object[10];
vector.add("AA");//elementData[0] ="AA"
vector.add("BB");//elementData[1] ="BB"
当添加到第11个元素时,数组已满,需要扩容.扩容至原来数组长度的两倍大小.并将原来的数组的内容copy到新new出来的数组.
3.LinkedList(链表)
(1). 特点
- 实现了List接口,可存储有序的,可重复的数据.
- 底层使用双向链表存储.
(2). 解析
LinkedList<String> list =new LinkedList<>();
//底层没做什么.
list.add("AA");//将"AA"封装到一个Node对象1中,list对象的属性first,last(类型Node<E>)都指向了该Node对象(first,last分别为指向链表的头结点的指针和尾结点的指针).
list.add("BB");//将"BB"封装到一个Node对象2中,并将last指针指向了Node对象2,Node对象里有属性(Node<E> prev, E item, Node<E> next),并将node1.next =node2,node2.prev =node1.构成了双向链表.
4.建议
(1). Vector基本上已经不使用了.被版本抛弃了.
(2). ArrayList底层使用Object[]数组结构.查找与尾部添加的时间复杂度为O(1);而删除与插入的时间复杂度为O(n).
(3). LinkedList底层使用双向链表存储.查找与尾部添加的时间复杂度为O(n);而删除与插入的时间复杂度为O(1).
(4). 在选择了ArrayList的前提下,重载构造器ArrayList list1 =new ArrayList();
//底层创建了长度为10的数组
ArrayList list2 =new ArrayList(int capacity)
//底层创建了长度为capacity的数组.