Collection
Collection是List棵逊、Queue和Set的超集伤疙,它直接繼承于Iterable
,也就是所有的Collection集合類都支持for-each循環(huán)辆影。除此之外徒像,Collection也是面向接口編程的典范,通過(guò)它可以在多種實(shí)現(xiàn)類間轉(zhuǎn)換蛙讥,這也是面向?qū)ο缶幊痰镊攘χ弧?/p>
方法定義
在閱讀源碼前锯蛀,我們可以先自行想象一下,如果我們想封裝下數(shù)組或鏈表以方便操作键菱,我們需要封裝哪些功能呢谬墙?比如:統(tǒng)計(jì)大小今布、插入或刪除數(shù)據(jù)经备、清空拭抬、是否包含某條數(shù)據(jù),等等侵蒙。而Collection就是對(duì)這些常用操作進(jìn)行提取造虎,只是其很全面、很通用纷闺。下面我們看看它都提供了哪些方法。
//返回集合的長(zhǎng)度,如果長(zhǎng)度大于Integer.MAX_VALUE六剥,返回Integer.MAX_VALUE
int size();
//如果集合元素總數(shù)為0尸执,返回true
boolean isEmpty();
//判斷集合中是否包含指定的元素,其依據(jù)是equals()方法
boolean contains(Object o);
//返回一個(gè)包含集合中所有元素的數(shù)組
Object[] toArray();
//與上個(gè)類似浸卦,只是增加了類型的轉(zhuǎn)換
<T> T[] toArray(T[] a);
//向集合中加入一個(gè)元素署鸡,如果成功加入則返回true,如果加入失敗限嫌,或者因集合本身已經(jīng)包含同個(gè)元素而不再加入時(shí)靴庆,返回false
boolean add(E e);
//從集合中刪除指定元素的單個(gè)實(shí)例
boolean remove(Object o);
//如果集合包含指定集合中的所有元素,返回true
boolean containsAll(Collection<?> c);
//把指定集合中的所有元素添加到集合中怒医,但在此期間炉抒,如果指定的集合發(fā)生了改變,可能出現(xiàn)意想不到的事情
boolean addAll(Collection<? extends E> c);
//從集合中刪除所有包含在指定集合中的元素
boolean removeAll(Collection<?> c);
//僅保留集合中包含在指定集合中的元素
boolean retainAll(Collection<?> c);
//清空集合
void clear();
//將此方法抽象稚叹,是保證所有子類都覆寫此方法焰薄,以保證equals的正確行為
boolean equals(Object o);
//同上
int hashCode();
//這個(gè)方法在JDK1.8中提供了默認(rèn)的實(shí)現(xiàn),會(huì)使用Iterator的形式刪除符合條件的元素
default boolean removeIf(Predicate<? super E> filter){
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
超級(jí)實(shí)現(xiàn)類:AbstractCollection
在Collection
中定義的許多方法扒袖,根據(jù)現(xiàn)有的定義以及繼承的Iterable
蛤奥,都可以在抽象類中實(shí)現(xiàn),這樣可以減少實(shí)現(xiàn)類需要實(shí)現(xiàn)的方法僚稿,這個(gè)抽象類就是AbstractCollection
凡桥。
首先我們關(guān)注下其文檔,里面有兩句說(shuō)明可能會(huì)影響我們的繼承:
To implement an unmodifiable collection, the programmer needs only to extend this class and provide implementations for the iterator and size methods. (The iterator returned by the iterator method must implement hasNext and next.)
To implement a modifiable collection, the programmer must additionally override this class's add method (which otherwise throws an UnsupportedOperationException), and the iterator returned by the iterator method must additionally implement its remove method.
大體意思是說(shuō)蚀同,如果要實(shí)現(xiàn)一個(gè)不可修改的集合缅刽,只需要重寫iterator
和size
接口就可以,并且返回的Iterator
需要實(shí)現(xiàn)hasNext
和next
蠢络。而要實(shí)現(xiàn)一個(gè)可以修改的集合衰猛,還必須重寫add
方法(默認(rèn)會(huì)拋出異常),返回的Iterator
還需要實(shí)現(xiàn)remove
方法刹孔。
方法定義
//這個(gè)毫無(wú)疑問(wèn)啡省,是可以直接獲取的
public boolean isEmpty() {
return size() == 0;
}
//這個(gè)方法因?yàn)镮terator的存在,可以進(jìn)行一致性封裝,這里需要注意的是對(duì)象的比較是通過(guò)equals方法卦睹,因?yàn)檎{(diào)用到了it.next()與it.hasNext()畦戒,這也是為什么文檔注釋會(huì)寫實(shí)現(xiàn)集合類需要重寫Iterator的這兩個(gè)方法。
public boolean contains(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return true;
} else {
while (it.hasNext())
if (o.equals(it.next()))
return true;
}
return false;
}
//和contains類似结序,也是通過(guò)Iterator實(shí)現(xiàn)的障斋,但其會(huì)調(diào)用it.remove()方法,這也是為什么文檔注釋會(huì)寫實(shí)現(xiàn)可以修改的集合類時(shí)需要重寫Iterator的remove方法徐鹤。
public boolean remove(Object o) {
//...省略垃环,這里調(diào)用了it.remove()方法
}
類似的方法還有containsAll(Collection<?> c)
、addAll(Collection<? extends E> c)
返敬、removeAll(Collection<?> c)
遂庄、retainAll(Collection<?> c)
和clear()
等,都需要利用到Iterator的特性劲赠,這里就不再一一贅述了涛目。
另外還有一個(gè)toArray()的方法實(shí)現(xiàn)略微不同,可以看看其具體實(shí)現(xiàn)经磅。
//這個(gè)實(shí)現(xiàn)相對(duì)復(fù)雜一些泌绣,可以看到擴(kuò)容最主要的手段是Arrays.copyOf()方法,
//也就是需要將原數(shù)組通過(guò)復(fù)制到新的數(shù)組中來(lái)實(shí)現(xiàn)的预厌。
//注意這里返回的順序和Iterator順序一致
//在這里實(shí)現(xiàn)是為了方便不同具體實(shí)現(xiàn)類互相轉(zhuǎn)換阿迈,我們?cè)诤罄m(xù)會(huì)多次見到此方法
public Object[] toArray() {
//先根據(jù)當(dāng)前集合大小聲明一個(gè)數(shù)組
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
//集合元素沒(méi)那么多,說(shuō)明不需要那么大的數(shù)組
if (! it.hasNext())
return Arrays.copyOf(r, i); //僅返回賦完值的部分
r[i] = it.next();
}
//元素比從size()中獲取的更多轧叽,就需要進(jìn)一步調(diào)整數(shù)組大小
return it.hasNext() ? finishToArray(r, it) : r;
}
private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
//記錄當(dāng)前大小
int i = r.length;
while (it.hasNext()) {
int cap = r.length;
//r的長(zhǎng)度不夠苗沧,繼續(xù)分配
if (i == cap) {
//擴(kuò)充方式為cap+cap/2+1,也就是1.5倍擴(kuò)容
int newCap = cap + (cap >> 1) + 1;
// 超過(guò)了最大容量炭晒,MAX_ARRAY_SIZE=Integer.MAX_VALUE-8
if (newCap - MAX_ARRAY_SIZE > 0)
//重新設(shè)置cap的值
newCap = hugeCapacity(cap + 1);
//對(duì)r進(jìn)行擴(kuò)容
r = Arrays.copyOf(r, newCap);
}
//賦值待逞,進(jìn)入下一輪循環(huán)
r[i++] = (T)it.next();
}
// 由于之前擴(kuò)容是1.5倍進(jìn)行的,最后再將其設(shè)置到和r實(shí)際需要的相同
return (i == r.length) ? r : Arrays.copyOf(r, i);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // 超過(guò)了最大正整數(shù)网严,也就是負(fù)數(shù)
throw new OutOfMemoryError
("Required array size too large");
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
//和toArray()方法類似识樱,就不再贅述,具體可以查看源碼
public <T> T[] toArray(T[] a) {
//...
}
除了以上這些方法震束,AbstractCollection
還實(shí)現(xiàn)了toString
方法怜庸,其是通過(guò)StringBuilder
拼接了每個(gè)元素的toString
完成的,也并不復(fù)雜垢村。這里可以看下其源碼:
public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
下一篇:Java集合源碼分析之List(一):超級(jí)接口List
我是飛機(jī)醬割疾,如果您喜歡我的文章,可以關(guān)注我~
編程之路嘉栓,道阻且長(zhǎng)宏榕。唯拓诸,路漫漫其修遠(yuǎn)兮,吾將上下而求索麻昼。