1. 集合類概述
Java中以一種比數(shù)組存儲更復雜的方式來存儲對象的一組對象---“容器類”,其基本類
型有List、Set和Map,它們被組織在以Collection及Map接口為根的層次結(jié)構(gòu)中,稱之為集合框架。
2. Collection接口
Collection的層次結(jié)構(gòu)圖
2.1 List篇
List的特征是其元素以線性的方式的存儲,集合中允許放重復元素。
List接口主要的實現(xiàn)類有:
- ArrayList() : 代表長度可以動態(tài)改變的數(shù)組;可以對元素進行隨機的訪問,向ArrayList
中插入與刪除元素的速度慢。
- LinkedList() : 采用鏈表結(jié)構(gòu)實現(xiàn)。其插入和刪除的速度快。
2.1.1 List遍歷方式:
(1)for循環(huán)遍歷
/**
* List中的get(int index)方法支持取指定下標的元素
*/
1)使用一般for循環(huán)
for(int i = 0 ; i < list.size ; i ++) {
E obj = list.get(i);
}
2)使用增強型for循環(huán)
for(E obj : list) {
}
(2)使用迭代器(Iterator)
/**
* Collection集合接口繼承了Iterator接口,允許集合被迭代
* 迭代方式如下:
*/
Iterator<E> it = list.iterator();
while(it.hasNext()) {
E obj = it.next();
}
2.1.2 ArrayList實現(xiàn)原理
ArrayList部分源碼分析:
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
// 存放元素的數(shù)組
private transient Object[] elementData;
/* 構(gòu)造方法,
* @param initialCapacity : 設(shè)置數(shù)組的初始容量
*/
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
}
從源碼可以分析出:ArrayList采用一個Object型對象數(shù)組來存放元素,默認初始容量為10。
public boolean add(E e) {
// 當添加元素時判斷數(shù)組容量超出可容納范圍時會自動擴容
// 具體會調(diào)用grow(int minCapacity)方法
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
// 該方法會自動給數(shù)組擴大一倍,數(shù)組可被擴大的最大容量為Integer.MAX_VALUE
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
....省略部分代碼
}
2.1.3 LinkedList實現(xiàn)原理
LinkedList采用雙向鏈表結(jié)構(gòu)來實現(xiàn)的,使用結(jié)點來存儲數(shù)據(jù)域和連接前一個和后一個結(jié)點.
static class Node<E> {
E item; // 用來保存數(shù)據(jù)域
Node<E> next; // 下一個結(jié)點
Node<E> prev; // 上一個結(jié)點
....此處省略
}
// 代指第一個結(jié)點
transient Node<E> first;
transient Node<E> last;
// 這里只做add方法的講解
public boolean add(E e) {
// 鏈接下一個結(jié)點
linkLast(e);
return true;
}
void linkLast(E e) {
// 保存當前的最后一個結(jié)點
final Node<E> l = last;
//創(chuàng)建一個新添加元素的結(jié)點,前一個結(jié)點為該鏈表的最后一個結(jié)點
final Node<E> newNode = new Node<E>(l , e , null);
// 將新結(jié)點作為最后一個結(jié)點
last = newNode;
// 如果未添加前最后一個結(jié)點為空,則說明此時鏈表沒有元素,將新結(jié)點作為首結(jié)點
// 否則將新結(jié)點鏈接在末尾
if(l != null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
LinkedList數(shù)據(jù)結(jié)構(gòu)是鏈式結(jié)構(gòu),具體查閱數(shù)據(jù)結(jié)構(gòu)相關(guān)的書籍。
2.1.4 ArrayList和LinkedList比較
ArrayList和LinkedList的區(qū)別:
1.ArrayList是實現(xiàn)了基于動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu)。
2.對于隨機訪問get和set,ArrayList覺得優(yōu)于LinkedList,因為LinkedList要移動指針。
3.對于新增和刪除操作add和remove,LinedList比較占優(yōu)勢,因為ArrayList要移動數(shù)據(jù)。
2.2 List使用場景
如果涉及到“棧”、“隊列”、“鏈表”等操作,應(yīng)該考慮用List,具體的選擇哪個List,根據(jù)下面的標準來取舍。
01) 對于需要快速插入,刪除元素,應(yīng)該使用LinkedList。
02) 對于需要快速隨機訪問元素,應(yīng)該使用ArrayList。
03) 對于“單線程環(huán)境” 或者 “多線程環(huán)境,但List僅僅只會被單個線程操作”,此時應(yīng)該使用非同步的類(如ArrayList)。
對于“多線程環(huán)境,且List可能同時被多個線程操作”,此時,應(yīng)該使用同步的類(如Vector)。