一、圖示
二、方法定義
我們先想一想,公司如果要我們自己去封裝一些操作數(shù)組或者鏈表的工具類,我么需要封裝哪些功能呢?不妨就是統(tǒng)計其 大小,增刪改查、清空或者是查看否含有某條數(shù)據(jù)等等。而collection接口就是把這些通常操作提取出來,使其更全面、更通用,那現(xiàn)在我們就來看看其源碼都有哪些方法。
//返回集合的長度,如果長度大于Integer.MAX_VALUE,返回Integer.MAX_VALUE
int size();
//如果集合元素總數(shù)為0,返回true
boolean isEmpty();
//判斷集合中是否包含指定的元素,其依據(jù)是equals()方法
boolean contains(Object o);
//返回一個包含集合中所有元素的數(shù)組
Object[] toArray();
//與上個類似,只是增加了類型的轉(zhuǎn)換
<T> T[] toArray(T[] a);
//向集合中加入一個元素,如果成功加入則返回true,如果加入失敗,或者因集合本身已經(jīng)包含同個元素而不再加入時,返回false
boolean add(E e);
//從集合中刪除指定元素的單個實例
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();
//這個方法在JDK1.8中提供了默認的實現(xiàn),會使用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;
}
三、超級實現(xiàn)類 AbstractCollection
通過以上的學習,我們可以知道在collection接口中,有很多通用的方法,根據(jù)現(xiàn)有的定義以及繼承的Iterable接口,都可以在抽象方法中實現(xiàn),這樣就可以減少具體實現(xiàn)類需要實現(xiàn)的方法,所以就有了這么一個類–AbstractCollection。
首先我們來看看api文檔對這個類的大概描述:
如果要實現(xiàn)一個不可修改的集合,只需要重寫Iterator和size接口就可以了,并且返回的Iterator需要實現(xiàn)hasNext和Next。而要實現(xiàn)一個可以修改的集合,還必須重寫add方法,返回的Iterator還要實現(xiàn)remove接口。
接下里我們來看看其方法定義
//這個毫無疑問,是可以直接獲取的
public boolean isEmpty() {
return size() == 0;
}
//這個方法因為Iterator的存在,可以進行一致性封裝,這里需要注意的是對象的比較是通過equals方法,因為調(diào)用到了it.next()與it.hasNext(),這也是為什么文檔注釋會寫實現(xiàn)集合類需要重寫Iterator的這兩個方法。
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類似,也是通過Iterator實現(xiàn)的,但其會調(diào)用it.remove()方法,這也是為什么文檔注釋會寫實現(xiàn)可以修改的集合類時需要重寫Iterator的remove方法。
public boolean remove(Object o) {
//...省略,這里調(diào)用了it.remove()方法
}
還有很多方法也用到了iterator的特性,例如containAll、addAll等等,這里就不一 一說明了。
除此之外,還有一個toArray方法,方法實現(xiàn)還有一些略微不同:
//這個實現(xiàn)相對復雜一些,可以看到擴容最主要的手段是Arrays.copyOf()方法,
//也就是需要將原數(shù)組通過復制到新的數(shù)組中來實現(xiàn)的。
//注意這里返回的順序和Iterator順序一致
//在這里實現(xiàn)是為了方便不同具體實現(xiàn)類互相轉(zhuǎn)換,我們在后續(xù)會多次見到此方法
public Object[] toArray() {
//先根據(jù)當前集合大小聲明一個數(shù)組
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
//集合元素沒那么多,說明不需要那么大的數(shù)組
if (! it.hasNext())
return Arrays.copyOf(r, i); //僅返回賦完值的部分
r[i] = it.next();
}
//元素比從size()中獲取的更多,就需要進一步調(diào)整數(shù)組大小
return it.hasNext() ? finishToArray(r, it) : r;
}
private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
//記錄當前大小
int i = r.length;
while (it.hasNext()) {
int cap = r.length;
//r的長度不夠,繼續(xù)分配
if (i == cap) {
//擴充方式為cap+cap/2+1,也就是1.5倍擴容
int newCap = cap + (cap >> 1) + 1;
// 超過了最大容量,MAX_ARRAY_SIZE=Integer.MAX_VALUE-8
if (newCap - MAX_ARRAY_SIZE > 0)
//重新設置cap的值
newCap = hugeCapacity(cap + 1);
//對r進行擴容
r = Arrays.copyOf(r, newCap);
}
//賦值,進入下一輪循環(huán)
r[i++] = (T)it.next();
}
// 由于之前擴容是1.5倍進行的,最后再將其設置到和r實際需要的相同
return (i == r.length) ? r : Arrays.copyOf(r, i);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // 超過了最大正整數(shù),也就是負數(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是怎么實現(xiàn)toString方法的吧+
其是通過StringBuilder拼接了每個元素的toString完成的,不是很復雜。
我們來看看源碼吧
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(' ');
}
}
到此這篇關(guān)于Java接口Collection的文章就介紹到這了,更多相關(guān)Java接口Collection 內(nèi)容,請搜索W3Cschool以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,也希望大家以后多多支持!