Java集合(二)、Collection接口介紹


一、Collection 接口概述

Collection是一個接口,繼承自Iterable。我們先看一下Iterable接口的源碼

package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;

    /**
     *實現這個接口的的類允許使用"for-each loop"語句來遍歷。
     */
public interface Iterable<T> {

    /**
     *返回一個元素類型為T的迭代器
     */
    Iterator<T> iterator();

    /**
     * jdk1.8新增的遍歷方式
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    /**
     * 暫不研究
     */
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

 

Iterable接口有一個Iterator iterator();方法,而Collection繼承自Iterable接口,所以我們說Collection因愛與Iterator。

 

二、Collection 接口

Collection是一個高度封裝的集合接口,它提供了所有集合要實現的默認方法接口。

我們看一下接口源碼,了解它有哪些接口和默認實現。

package java.util;

import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 *這是一個集合分層的根接口。集合代表了一組包含元素的對象。有些集合允許有重復的元素,有些不允許。
 *有些集合是有序的有些無序的。jdk不對這個接口提供任何直接的實現,但是再一些直接子接口例如Set和List有實現了某些接口方法。
 *所有繼承Collection的類必須提供兩個默認的構造函數,一個不帶參數的、一個帶Collection類型參數。
 *
 */

public interface Collection<E> extends Iterable<E> {
    //查詢操作

    /**
     *返回集合大小,也就是集合中元素的數量
     */
    int size();

    /**
     * 如果集合包含元素則返回true,即判斷集合是否為空
     */
    boolean isEmpty();

    /**
     * 判斷集合是否存在某個對象,注意這里參數是個Object,並沒有限制為E或其子類
     */
    boolean contains(Object o);

    /**
     * 返回一個迭代器iterator。並沒有說明元素的迭代順序,除非特別的集合有這個要求。
     */
    Iterator<E> iterator();

    /**
     *將集合轉為對象數組,注意這里不是元素數組而是一個Object數組。
     *如果集合保證是有序的,那么通過迭代器返回數組有相同順序
     *返回的數組是安全的,也就是說集合有自己的引用,數組開辟新的堆內存,也有自己的引用。所以調
     *用者可以隨意操作返回的數組。
     *這個方法是數組和列表之間的橋梁
     */
    Object[] toArray();

    /**
     * 返回一個集合元素類型的數組。如果集合滿足指定的數組並且有足夠的空間,則在其中返回此集合
     * 否則返回此集合大小的新數組。
     * 如果集合有序,那么返回此集合迭代器遍歷順序的數組
     * 如果數組大小比集合元素多,那么在數組滿足集合元素后在末尾設置為null  
     *
     * 如果在這個集合中指定數組運行時類型不是運行時元素類型的超類,那么拋ArrayStoreException異常
     * 如果指定數組為空,則拋出NullPointerException
     */
    <T> T[] toArray(T[] a);


    //修改操作

    /**
     * 確保此集合包含特定的元素類型。
     * 如果此集合增加元素成功返回true。
     * 如果此集合不允許有重復元素並且已經包含所傳參數,那么返回false
     * 
     * 支持此操作的集合可能會限制向該集合添加哪些元素。特別的,有些集合會拒絕null元素,有些
     * 會對要增加的元素強加一些限制。
     * Collection實現類應該在文檔中明確指出所有的限制。
     *
     * 如果集合以除已經包含元素之外的任何原因拒絕添加特定元素,則必須拋出異常
     *(而不是返回false)。這保留了集合在此調用返回后始終包含指定元素的不變式。
     */
    boolean add(E e);

    /**
     * 如果此集合中存在此元素,那么移除一個特定元素類型的實例。更正式的說,如果集合中包含一個或多個這樣的元素,
     * 那么刪除這樣的元素(o==null?e==null:o.equals(e))。如果集合包含指定的元素(或集合因調用而發生改變),那么返回true。
     *
     * 如果指定元素的類型和集合不相容,拋出ClassCastException異常(可選的限制條件)
     * 如果指定元素是null並且這個集合不允許null元素存在,那么拋出NullPointerException異常(可選的限制條件)
     * 如果此集合不支持remove操作那么拋出UnsupportedOperationException異常(可選的限制條件)
     */
    boolean remove(Object o);


    //容量操作

    /**
     * 如果this集合包含指定集合的所有元素,返回true
     * c集合必須要檢查是否被包含在this集合
     * 如果指定元素的類型和集合不相容,拋出ClassCastException異常(可選的限制條件)
     * 如果指定元素是null並且這個集合不允許null元素存在,那么拋出NullPointerException異常(可選的限制條件)
     */
    boolean containsAll(Collection<?> c);

    /**
     * 將指定集合的所有元素到this集合中(可選的操作)。
     * 如果指定的集合在操作進行時被修改了,那么此操作行為未定義。
     * (這意味着如果指定的集合是這個集合,並且這個集合是非空的,那么這個調用的行為是未定義的。)
     * 
     * @參數:c集合包含了要被添加到這個集合的元素
     * @返回:如果調用結果改變了this集合返回true
     * @throws:如果 addAll操作不被此集合支持,那么拋出UnsupportedOpertaionException異常
     * @throws: 如果指定集合包含了空元素而this集合不允許有空元素,那么拋出NullPointerException異常
     * @throws:如果this集合阻止hiding集合元素類型添加,那么拋出ClassCastException異常
     * @throws:如果指定集合的元素的某些屬性阻止將其添加到此集合,則拋出IllegalArgumentException
     * @throws:由於插入限制,如果不是所有元素都可以在此時添加,則拋出IllegalStateException異常
     */
    boolean addAll(Collection<? extends E> c);

    /**
     * 移除此集合中所有的包含在指定集合中的元素(可選的操作)。調用過此函數之后,那么此集合和指定集合將不再包含相同元素。
     *
     * @param:包含要從該集合中刪除的元素的c集合
     * @return:如果此集合因調用而更改那么返回true
     * @throws:如果此集合不支持removeAll方法,則拋出UnsupportedOperationException
     * @throws:如果集合中一個或多個元素的類型與指定集合不兼容,則拋出ClassCastException(可選的操作)
     * @throws:如果該集合包含一個或多個空元素,且指定的集合不支持空元素(optional),或者指定的集合為空,
     * 則拋出NullPointerException異常
     */
    boolean removeAll(Collection<?> c);

    /**
     * 移除此集合中所有符合給定Predicate的元素。在迭代期間或由Predicate引發的錯誤或運行時異常將被轉發給調用方
     * @implSpec
     * 默認實現使用其迭代器遍歷集合的所有元素。每一個匹配的元素使用iterator.remove()來移除。
     * 如果集合的iterator不支持移除將會拋出UnsupportedOperationException異常在匹匹厄到
     * 第一個元素時。
     * @param 過濾一個predicate
     * @param 篩選要刪除的元素返回true的Predicate
     * @return 如果任何一個元素被刪除返回true
     * @throws 指定過濾器為空,拋出NullPointerException
     * @throws 如果元素沒有被刪除,或者移除操作不支持,
     *  則立即拋出UnsupportedOperationException異常
     * @since 1.8
     */
    default boolean removeIf(Predicate<? super E> filter) {
        //如果filter為null拋出NullPointerException
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        //通過迭代器遍歷刪除,只要刪除一個removed就為true
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }

    /**
     * 只保留此集合中包含在指定集合中的元素(可選的操作)。
     * 也就是說,此集合中不包含在指定集合中的所有元素。
     * @param:要保留的元素的集合c
     * @return:如果此集合改變了返回true
     * @throws:如果此集合不支持retainAll,則拋出UnsupportedOperationException異常
     * @throws:如果集合中一個或多個元素的類型與指定集合不兼容,則拋出ClassCastException(可選的操作)
     * @throws:如果該集合包含一個或多個空元素,且指定的集合不支持空元素(optional),或者指定的集合為空
     */
    boolean retainAll(Collection<?> c);

    /**
     * 移除此集合中所有元素(可選操作),調用此方法后集合里將為空。
     * @throws: 如果此集合clear操作不支持將會拋出UnsupportOperationException異常。
     */
    void clear();



    //比較和hash

    /**
     * 比較指定的對象與此集合是否相等
     * 
     */
    boolean equals(Object o);

    /**
     *返回這個集合的hashCode。當集合接口沒有對Object.hashCode方法的一般協議做任何規定,編程
     *人員應該注意在重寫equals方法時必須重寫hashCode方法,以便滿足一般協議對這個
     *Object.hashCode方法。特別的,c1.equals(c2)表明c1.hashCode()==c2.hashCode()。
     */
    int hashCode();

    /**
     *一下1.8新增的Spliterator,暫不研究
     */
    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}

 

三、AbstractCollection類

AbstractCollection是一個實現了Collection接口的抽象類,除了iterator()和size()接口,它提供了一些其他接口的默認實現,其他集合類可以繼承此類來復用。

AbstractCollection源碼

package java.util;

public abstract class AbstractCollection<E> implements Collection<E> {
    /*唯一的構造函數*/
    protected AbstractCollection(){

    }

    //查詢操作

    public abstract Iterator<E> iterator();

    public abstract int size();

    /*
     * 返回size() == 0
     */
    public boolean isEmpty(){
        return size() == 0;
    }

    /**
     * 實現的contains方法,通過迭代器遍歷
     */
    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;
    }

    /**
     * 此默認實現,考慮到數組在迭代器遍歷過程中大小可能會改變,
     * 也就是可能會增加或減少元素怒
     */
    public Object[] toArray(){
        //估計數組大小,並做好變小或變大的准備
        Object[] r = new Object[size()];
        Iterator<E> it = iterator();
        for (int i = 0; i < r.length; i++){
            if (! it.hasNext())  //比期望的元素少,那么調用Arrays.copyOf()方法返回一個新的數組
                return Arrays.copyOf(r, i);
            r[i] = it.next();
        }
        //判斷集合有沒有被增加(迭代器改變),如果沒有返回數組,如果有調用finishToArray()方法返回數組
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    /**
     * 
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        // Estimate size of array; be prepared to see more or fewer elements
        int size = size();
        T[] r = a.length >= size ? a :
                  (T[])java.lang.reflect.Array
                  .newInstance(a.getClass().getComponentType(), size);
        Iterator<E> it = iterator();

        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext()) { // fewer elements than expected
                if (a == r) {
                    r[i] = null; // null-terminate
                } else if (a.length < i) {
                    return Arrays.copyOf(r, i);
                } else {
                    System.arraycopy(r, 0, a, 0, i);
                    if (a.length > i) {
                        a[i] = null;
                    }
                }
                return a;
            }
            r[i] = (T)it.next();
        }
        // more elements than expected
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    /**
     * 一些VM會在數組中保留頭信息,所以要占用8字節空間,頭信息大小不能超過8
     * 重新分配更大的長度給數組,如果要求的數組大小超過VM限制,會拋出OutOfMemoryError
     * 默認值 2147483647 - 8;
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * 重新在toArray方法中,如果iterator返回了比期望中的大小更多的元素時,重新給數組分配空間來完成填充數組。
     * @param 之前的已經被填滿的數組
     * @param 操作中集合的iterator
     * @return 除了給定的數組之外,增加了從迭代器中獲取的元素,並修正數組長度
     */
    @SuppressWarnings("unchecked")
    private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
        int i = r.length; //被填充滿的數組長度(原始集合大小)
        while (it.hasNext()) {
            int cap = r.length;
            if (i == cap) {  //第一次(剛進來的時候)一定為true,那么分配新的數組大小
                int newCap = cap + (cap >> 1) + 1; //右移一位+1再加上原大小
                if (newCap - MAX_ARRAY_SIZE > 0)  
                    //新數組大小大於集合默認最大值,調用hugeCapacity()方法重新分配,值為Integer.MAX_VALUE
                    newCap = hugeCapacity(cap + 1);
                r = Arrays.copyOf(r, newCap);
            }
            r[i++] = (T)it.next();
        }
        // 修正數組多余的空間,如果正好直接返回,否則調用Arrays.copyOf()方法
        return (i == r.length) ? r : Arrays.copyOf(r, i);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // 內存溢出
            throw new OutOfMemoryError
                ("Required array size too large");
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }



    //修改操作
    /**
     * 此操作總是拋出 UnsupportedOperationException
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IllegalStateException         {@inheritDoc}
     */
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }

    /**
     * 通過集合迭代器查找元素,如果找到調用iterator.remove()方法刪除元素。
     * 刪除一個就返回true
     */
    public boolean remove(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext()) {
                if (it.next()==null) {
                    it.remove();
                    return true;
                }
            }
        } else {
            while (it.hasNext()) {
                if (o.equals(it.next())) {
                    it.remove();
                    return true;
                }
            }
        }
        return false;
    }

    // Bulk Operations
    /**
     * 判斷此集合是否包含指定集合所有元素,有一個沒有返回false
     */
    public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }

    /**
     * 調用add(E e)方法添加指定集合到此集合中
     *
     * @see #add(Object)
     */
    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }

    /**
     * 這個方法將從此集合中刪除指定集合的所有元素,通過迭代器刪除。
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     *
     * @see #remove(Object)
     * @see #contains(Object)
     */
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<?> it = iterator();
        while (it.hasNext()) {
            if (c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

    /**
     * 此集合中保留指定集合的所有元素,也就是說調用此方法之后,此集合中刪除了不存在指定集合中
     *的元素
     * 
     */
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            if (!c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

    /**
     * 清空集合中所有元素
     * @throws UnsupportedOperationException {@inheritDoc}
     */
    public void clear() {
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
        }
    }


    //  String conversion

    /**
     * 集合的toString方法,所有繼承AbstractCollection的類都有此方法
     */
    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            //如果將自己這個集合添加到自己,就會打印(this Collection)
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

}
}

AbstractCollection類默認實現的方法,在上面源代碼中我都已經講解過了,很多常用的集合都會使用 默認實現,比如常用的toString方法,我們在輸出ArrayList時調用的就是此方法。

 

 

引自:http://www.manongjc.com/article/66616.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM