List是有序且元素可重復(fù)集合
ArrayList
ArrayList實(shí)現(xiàn)了一個(gè)可變大小的數(shù)組,允許包含所有的元素,包括null。
由于ArrayList實(shí)現(xiàn)了List接口,所以ArrayList存儲(chǔ)的元素是有序,按照添加元素的先后順序進(jìn)行排列。當(dāng)然也可以通過(guò)Collections.sort(List<T> list);對(duì)ArrayList內(nèi)的元素進(jìn)行排序,但需要注意該方法的泛型參數(shù)類(lèi)型應(yīng)該是Comparable類(lèi)型,所以ArrayList中的元素需要實(shí)現(xiàn)Comparable接口,并實(shí)現(xiàn)其int compareTo(T o)方法
每一個(gè)ArrayList實(shí)例都會(huì)有一個(gè)初始容量Capacity,默認(rèn)為10,你可以在構(gòu)造實(shí)例時(shí)根據(jù)需要設(shè)定改容量的大小,如下:
ArrayList arrayList = new ArrayList<Integer>(20);
在插入大量數(shù)據(jù)時(shí),為了提升性能,可以調(diào)用ArrayList中的ensureCapacity(int minCapacity)方法來(lái)增加ArrayList容量,從而提高插入的效率。
需要注意的是,ArrayList是非線程安全的,如果多個(gè)線程同時(shí)訪問(wèn)同一個(gè)ArrayList實(shí)例,并且其中至少有一個(gè)線程對(duì)ArrayList實(shí)例進(jìn)行了修改,為了保證線程安全,需要在外部實(shí)現(xiàn)同步。你也可以這樣創(chuàng)建一個(gè)同步的ArrayList實(shí)例:
Collections.synchronizedList(new ArrayList<Integer>());
ArrayList支持快速隨機(jī)訪問(wèn),訪問(wèn)某個(gè)元素的事件復(fù)雜度是O(1).但是插入和刪除元素的操作速度很慢。
CopyOnWriteArrayList
CopyOnWriteArrayList同ArrayList一樣,底層仍然是一個(gè)可變大小的數(shù)組實(shí)現(xiàn)的,但CopyOnWriteArrayList的不同卻在于其利用了高并發(fā)往往是讀多寫(xiě)少的特性,對(duì)讀操作不加鎖,對(duì)寫(xiě)操作加鎖。
源碼中,對(duì)于寫(xiě)操作add(E e) | set(E e) | remove(int index),在進(jìn)入方法后,首先加鎖,然后復(fù)制一份新的數(shù)組,對(duì)新數(shù)組進(jìn)行相應(yīng)操作,然后將新數(shù)組賦給舊的引用,然后再解鎖。
由于CopyOnWriteArrayList在進(jìn)行寫(xiě)操作時(shí),對(duì)容器的基本數(shù)組進(jìn)行了復(fù)制,內(nèi)存開(kāi)銷(xiāo)會(huì)比較大,所以不適于存儲(chǔ)大數(shù)據(jù)量。
LinkedList
LinkedList底層是一個(gè)鏈表的實(shí)現(xiàn),因此在內(nèi)部有許多具有鏈表特色的方法,比如:
public void addFirst(E e)//在表頭插入元素
public void addLast(E e)//在表尾插入元素
public E getFirst()//獲取鏈表的頭(第一個(gè))元素
public E getLast()//獲取鏈表的尾(最后一個(gè))元素
public E pop()
public E push()
...
在這里就不一一介紹了。
LinkedList是非線程安全的,這一點(diǎn)同ArrayList是一樣的,獲取同步的LinkedList,可以這樣做:
Collections.synchronizedList(new LinkedList<Integer>());
由于LinkedList是鏈表結(jié)構(gòu)的,所以其插入操作的時(shí)間復(fù)雜度是常量級(jí)的,但是查找、刪除和更新的操作是O(n)。
Vector
Vector和ArrayList非常相似,底層也是一個(gè)可變長(zhǎng)的數(shù)組,但是Vector是線程安全的,因此單純從性能尚來(lái)說(shuō),Vector的性能要低于ArrayList,但Vector類(lèi)中也提供了一些,去盡可能的提升性能,優(yōu)化內(nèi)存存儲(chǔ)
/*
構(gòu)造方法,使用制定的初始容量和容量增量實(shí)例化對(duì)象
*/
public Vector(int initialCapacity, int capacityIncrement)
public int capacity()//返回當(dāng)前容量
public void ensureCapacity (int minCapacity)//增加容量
public void trimToSize()//對(duì)實(shí)例的容量進(jìn)行微調(diào),使其等于實(shí)例中元素的數(shù)量
Stack
Stack是Vector的子類(lèi),所以改類(lèi)也是線程安全的。其實(shí)現(xiàn)了數(shù)據(jù)結(jié)構(gòu)中棧,具有元素后進(jìn)先出(LIFO)的規(guī)則。具有通常的push pop和peek操作。
遍歷操作
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
1.foreach遍歷的方式
for(Integer i : list){
System.out.println(i);
}
2.普通for循環(huán)遍歷的方式
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
注意前兩種方式在循環(huán)內(nèi)部都不能對(duì)集合的結(jié)構(gòu)進(jìn)行修改
3.iterator遍歷的方式
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
4.listIterator遍歷的方式
ListIterator<Integer> listIterator = list.listIterator();
while(listIterator.hasNext()){
System.out.println(listIterator.next());
}
iterator和listIterator的相同與不同
相同點(diǎn):1>都可以對(duì)List集合進(jìn)行遍歷。這兩個(gè)方法都是快速失敗的,也就是說(shuō)除非調(diào)用迭代器內(nèi)部修改集合集合的方法,否則無(wú)論在何處無(wú)論在何時(shí)修改集合都會(huì)產(chǎn)生快速失敗,迭代器都會(huì)拋出ConcurrentModificationException運(yùn)行時(shí)異常。
不同點(diǎn):2>iterator可以用于多種集合,set、list、Map都可,而listIterator只能用于list集合
3>兩者包含的方法不同。比如,ListIterator中有add()方法,而Iterator中沒(méi)有
4>ListIterator可以實(shí)現(xiàn)雙向遍歷,而Iterator只能單向向后(next())遍歷