Collections中的内部集合類
源碼基于1.8.0_112
Collections中提供了大量的集合類,以代理的方式對現有的集合進行了功能上的修改。
總共有以下幾類集合:
Unmodifiable:不可修改的集合類
Synchronized:同步的集合類
Checked:類型安全的集合類
Empty:空集合類
Empty:隻有單個元素的集合類
由于各類以上幾類集合對List、Map、Set的實作較為相似,我們隻分析List。
原理:Collections中的内部集合類為傳入的類作為代理,改變傳入集合的行為。
UnmodifiableCollection
UnmodifiableCollection是所有Unmodifiable類的父類
UnmodifiableCollection用一個成員變量儲存傳入對象,然後為該對象提供代理
UnmodifiableList是UnmodifiableCollection的其中一個子類
UnmodifiableList也會用一個成員變量儲存傳入對象,然後為該對象提供代理
UnmodifiableCollection和UnmodifiableList各自儲存一份被代理對象的引用(指向同一個對象)。
以上都是套路,之後的集合不再介紹
UnmodifiableCollection将傳入的集合修包裝成一個不可變的集合。
代碼
/**
* 所有Unmodifiable内部類的父類
* @param <E>
*/
static class MyUnmodifiableCollection<E> implements Serializable {
// 序列化ID
private static final long serialVersionUID = L;
// 存儲集合類
final Collection<? extends E> c;
// 構造函數需要傳入一個集合類
MyUnmodifiableCollection(Collection<? extends E> c) {
if (c == null)
throw new NullPointerException();
this.c = c;
}
// 實作行為相同的方法,以代理的方式通路傳入的集合類
public int size() {
return c.size();
}
public boolean isEmpty() {
return c.isEmpty();
}
public boolean contains(Object o) {
return c.contains(o);
}
public Object[] toArray() {
return c.toArray();
}
public <T> T[] toArray(T[] a) {
return c.toArray(a);
}
public String toString() {
return c.toString();
}
// 修改操作抛出UnsupportedOperationException異常
public boolean add(E e) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
}
/**
* List實作類
* @param <E>
*/
static class MyUnmodifiableList<E> extends MyUnmodifiableCollection<E> {
private static final long serialVersionUID = -L;
// 存儲集合
final List<? extends E> list;
// 需要一個傳入List來建構MyUnmodifiableList
MyUnmodifiableList(List<? extends E> list) {
// 調用父類構造函數
super(list);
// 子類指派
this.list = list;
}
// 代理通路方法
public E get(int index) {
return list.get(index);
}
public int indexOf(Object o) {
return list.indexOf(o);
}
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
// 所有修改的操作,都會被禁止
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
public boolean addAll(int index, Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
}
SynchronizedCollection
SynchronizedCollection應該算是一個比較重的的集合,他會把傳入的集合包裝成一個線程安全的集合類
SynchronizedCollection和Vector做一個比較:
1. SynchronizedCollection具有更加合理的結構
2. SynchronizedCollection可以自定義鎖對象
3. SynchronizedCollection沒有對疊代器做同步處理。Vector疊代每次的next操作都會加鎖,這樣會頻繁的加鎖,性能可想而知。我們更希望的是,在疊代前加鎖,将整個疊代過程放在同步塊中,這樣就隻會進行一次加鎖操作,SynchronizedCollection正是希望我們會這麼做。
4. 總之SynchronizedCollection更加的自由,更加推薦被使用。
總結:再需要使用同步集合的時候,我們可以選擇SynchronizedCollection和CopyOnWriteArrayList
SynchronizedCollection:一般情況下使用,注意自行同步部分方法
CopyOnWriteArrayList:集合修較少被修改的情況下使用
代碼
static class SynchronizedCollection<E> implements Serializable {
final Collection<E> c; // Backing Collection
// 鎖對象
final Object mutex; // Object on which to synchronize
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
SynchronizedCollection(Collection<E> c, Object mutex) {
this.c = Objects.requireNonNull(c);
this.mutex = Objects.requireNonNull(mutex);
}
// 對操作進行加鎖處理
public int size() {
synchronized (mutex) {return c.size();}
}
// 疊代器未進行同步
public Iterator<E> iterator() {
return c.iterator(); // Must be manually synched by user!
}
public boolean add(E e) {
synchronized (mutex) {return c.add(e);}
}
public boolean remove(Object o) {
synchronized (mutex) {return c.remove(o);}
}
}
static class SynchronizedList<E> extends SynchronizedCollection<E>{
final List<E> list;
SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}
public ListIterator<E> listIterator() {
return list.listIterator(); // Must be manually synched by user
}
}
CheckedCollection
CheckedCollection必須指定類型,将傳入對象包裝成一個類型安全的集合
CheckedCollection插入時會檢查類型,確定集合是類型安全的
代碼
/**
* 類型安全的集合
*
* @param <E>
*/
static class CheckedCollection<E> implements Serializable {
private static final long serialVersionUID = L;
final Collection<E> c;
final Class<E> type;
@SuppressWarnings("unchecked")
E typeCheck(Object o) {
if (o != null && !type.isInstance(o))
throw new ClassCastException(badElementMsg(o));
return (E) o;
}
private String badElementMsg(Object o) {
return "Attempt to insert " + o.getClass() +
" element into collection with element type " + type;
}
// 必須制定類型
CheckedCollection(Collection<E> c, Class<E> type) {
this.c = Objects.requireNonNull(c, "c");
this.type = Objects.requireNonNull(type, "type");
}
public int size() {
return c.size();
}
public boolean remove(Object o) {
return c.remove(o);
}
}
static class CheckedList<E> extends CheckedCollection<E> {
private static final long serialVersionUID = L;
final List<E> list;
CheckedList(List<E> list, Class<E> type) {
super(list, type);
this.list = list;
}
public E get(int index) {
return list.get(index);
}
public E remove(int index) {
return list.remove(index);
}
public E set(int index, E element) {
return list.set(index, typeCheck(element));
}
// 插入時需要驗證類型
public void add(int index, E element) {
list.add(index, typeCheck(element));
}
}
EmptyList
EmptyList提供一個空的對象,對象不可修改。
Collections中有一個EMPTY_LIST成員變量,該變量為static
例如:某個函數傳回一個List,如果傳回的List不存在。那麼我們不應該傳回null,而是使用一個空對象代替。這時候我們可以使用
return Collections.EMPTY_LIST;
代碼
// Collections成員變量
public static final List EMPTY_LIST = new EmptyList<>();
/**
* 空對象
*/
private static class EmptyList<E> extends AbstractList<E> implements RandomAccess, Serializable {
public int size() {return ;}
public boolean isEmpty() {return true;}
public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
SingletonList
SingletonList内隻允許存儲一個元素,該元素在List初始化時确定。
代碼
/**
* 單元素對象
* @param <E>
*/
private static class SingletonList<E> extends AbstractList<E> implements RandomAccess, Serializable {
private static final long serialVersionUID = L;
private final E element;
// 初始化時傳入一個元素
SingletonList(E obj) {
element = obj;
}
public int size() {
return ;
}
// 隻允許傳回第一個元素
public E get(int index) {
if (index != )
throw new IndexOutOfBoundsException("Index: " + index + ", Size: 1");
return element;
}
}
總結
Collections中的内部集合類對原始集合類做了一些擴充和定制,畢竟Collections算是一個工具類。