国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

Java源碼解析之接口Collection

發(fā)布時(shí)間:2021-07-05 18:40 來(lái)源:腳本之家 閱讀:0 作者:不會(huì )編程的派大星 欄目: 開(kāi)發(fā)技術(shù)

目錄

一、圖示

二、方法定義

我們先想一想,公司如果要我們自己去封裝一些操作數組或者鏈表的工具類(lèi),我么需要封裝哪些功能呢?不妨就是統計其 大小,增刪改查、清空或者是查看否含有某條數據等等。而collection接口就是把這些通常操作提取出來(lái),使其更全面、更通用,那現在我們就來(lái)看看其源碼都有哪些方法。

//返回集合的長(cháng)度,如果長(cháng)度大于Integer.MAX_VALUE,返回Integer.MAX_VALUE
int size();

//如果集合元素總數為0,返回true
boolean isEmpty();

//判斷集合中是否包含指定的元素,其依據是equals()方法
boolean contains(Object o);

//返回一個(gè)包含集合中所有元素的數組
Object[] toArray();

//與上個(gè)類(lèi)似,只是增加了類(lèi)型的轉換
<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ā)生了改變,可能出現意想不到的事情
boolean addAll(Collection<? extends E> c);

//從集合中刪除所有包含在指定集合中的元素
boolean removeAll(Collection<?> c);

//僅保留集合中包含在指定集合中的元素
boolean retainAll(Collection<?> c);

//清空集合
void clear();

//將此方法抽象,是保證所有子類(lèi)都覆寫(xiě)此方法,以保證equals的正確行為
boolean equals(Object o);

//同上
int hashCode();

//這個(gè)方法在JDK1.8中提供了默認的實(shí)現,會(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;
}

三、超級實(shí)現類(lèi) AbstractCollection

通過(guò)以上的學(xué)習,我們可以知道在collection接口中,有很多通用的方法,根據現有的定義以及繼承的Iterable接口,都可以在抽象方法中實(shí)現,這樣就可以減少具體實(shí)現類(lèi)需要實(shí)現的方法,所以就有了這么一個(gè)類(lèi)–AbstractCollection。

首先我們來(lái)看看api文檔對這個(gè)類(lèi)的大概描述:

如果要實(shí)現一個(gè)不可修改的集合,只需要重寫(xiě)Iterator和size接口就可以了,并且返回的Iterator需要實(shí)現hasNext和Next。而要實(shí)現一個(gè)可以修改的集合,還必須重寫(xiě)add方法,返回的Iterator還要實(shí)現remove接口。

接下里我們來(lái)看看其方法定義

//這個(gè)毫無(wú)疑問(wèn),是可以直接獲取的
public boolean isEmpty() {
    return size() == 0;
}

//這個(gè)方法因為Iterator的存在,可以進(jìn)行一致性封裝,這里需要注意的是對象的比較是通過(guò)equals方法,因為調用到了it.next()與it.hasNext(),這也是為什么文檔注釋會(huì )寫(xiě)實(shí)現集合類(lèi)需要重寫(xiě)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類(lèi)似,也是通過(guò)Iterator實(shí)現的,但其會(huì )調用it.remove()方法,這也是為什么文檔注釋會(huì )寫(xiě)實(shí)現可以修改的集合類(lèi)時(shí)需要重寫(xiě)Iterator的remove方法。
public boolean remove(Object o) {
    //...省略,這里調用了it.remove()方法
}

還有很多方法也用到了iterator的特性,例如containAll、addAll等等,這里就不一 一說(shuō)明了。

除此之外,還有一個(gè)toArray方法,方法實(shí)現還有一些略微不同:

//這個(gè)實(shí)現相對復雜一些,可以看到擴容最主要的手段是Arrays.copyOf()方法,
//也就是需要將原數組通過(guò)復制到新的數組中來(lái)實(shí)現的。
//注意這里返回的順序和Iterator順序一致
//在這里實(shí)現是為了方便不同具體實(shí)現類(lèi)互相轉換,我們在后續會(huì )多次見(jiàn)到此方法
public Object[] toArray() {
    //先根據當前集合大小聲明一個(gè)數組
    Object[] r = new Object[size()];
    Iterator<E> it = iterator();
    for (int i = 0; i < r.length; i++) {
        //集合元素沒(méi)那么多,說(shuō)明不需要那么大的數組
        if (! it.hasNext()) 
            return Arrays.copyOf(r, i); //僅返回賦完值的部分
        r[i] = it.next();
    }
    //元素比從size()中獲取的更多,就需要進(jìn)一步調整數組大小
    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的長(cháng)度不夠,繼續分配
        if (i == cap) {
            //擴充方式為cap+cap/2+1,也就是1.5倍擴容
            int newCap = cap + (cap >> 1) + 1;
            // 超過(guò)了最大容量,MAX_ARRAY_SIZE=Integer.MAX_VALUE-8
            if (newCap - MAX_ARRAY_SIZE > 0)
                //重新設置cap的值
                newCap = hugeCapacity(cap + 1);
            
            //對r進(jìn)行擴容
            r = Arrays.copyOf(r, newCap);
        }
        //賦值,進(jìn)入下一輪循環(huán)
        r[i++] = (T)it.next();
    }
    // 由于之前擴容是1.5倍進(jìn)行的,最后再將其設置到和r實(shí)際需要的相同
    return (i == r.length) ? r : Arrays.copyOf(r, i);
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // 超過(guò)了最大正整數,也就是負數
        throw new OutOfMemoryError
            ("Required array size too large");
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

//和toArray()方法類(lèi)似,就不再贅述,具體可以查看源碼
public <T> T[] toArray(T[] a) {
    //...
}

除了這些,我們再來(lái)看看AbstractCollection是怎么實(shí)現toString方法的吧+

其是通過(guò)StringBuilder拼接了每個(gè)元素的toString完成的,不是很復雜。

我們來(lái)看看源碼吧

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 內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

国产特级毛片AAAAAA高清| 蜜臀AV无码一区二区三区| 免费男人下部进女人下部视频| 中文字幕久久精品一二三区| 妺妺窝人体色WWW看人体| 久久综合给合久久狠狠狠97色|