詳解Java集合框架

簡(jiǎn)介

Java最初版本只實(shí)現(xiàn)了一些常用的數(shù)據(jù)結(jié)構(gòu),并提供了這些類或接口Vector,Stack,Hashtable,BitSet,Enumeration接口來(lái)實(shí)現(xiàn)這些結(jié)構(gòu)。

其中Enumeration接口提供了讓我們能枚舉任意容器元素的抽象機(jī)制。

特點(diǎn)

將集合的接口與實(shí)現(xiàn)分離

這一點(diǎn)我們可以從常見的隊(duì)列Queue的設(shè)計(jì)上看出來(lái),隊(duì)列的原則是尾部添加元素,在隊(duì)列的頭部刪除元素,可以看到Java的實(shí)現(xiàn)是首先定義了一個(gè)接口,里面定義了一些Queue的常用操作方法,

public interface Queue<E> extends Collection<E> {
    ...
    boolean add(E e);
    boolean offer(E e);
    E remove();
    ...
}

然后在根據(jù)不同的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)隊(duì)列,通常情況下隊(duì)列使用兩種數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn),循環(huán)數(shù)組和鏈表,如下圖:

這樣在編程的時(shí)候只需要更換實(shí)現(xiàn)類就可以輕松的切換所使用的數(shù)據(jù)結(jié)構(gòu)了。

Collection

可以看到上面的Queue都繼承Collection,其實(shí)集合類的都是繼承了他,他提供了幾個(gè)最基本的方法:

public interface Collection<E> extends Iterable<E> {
    boolean add(E e);
    Iterator<E> iterator();
}

當(dāng)然還有其他方法。

add:添加一個(gè)元素

iterator:返回一個(gè)實(shí)現(xiàn)了Iterator接口的對(duì)象。使用它可以很方便的訪問(wèn)集合中的元素。

Iterator

Iterator接口包含的方法:

public interface Iterator<E> {    
    boolean hasNext();
 
    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

遍歷元素的方式通過(guò)反復(fù)調(diào)用next方法即可訪問(wèn)每個(gè)元素,但是如果達(dá)到了集合末尾,將拋出NoSuchElementException,所以在調(diào)用next方法前要先調(diào)用hasNext方法檢測(cè)。

ArrayList<String> strings = new ArrayList<>();
strings.add("a");
strings.add("b");
strings.add("c");
strings.add("d");
strings.add("e");

Iterator<String> iterator = strings.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

當(dāng)然也可以通過(guò)foreach循環(huán)遍歷:

for (String s :
       strings ) {
    System.out.println(s);
}

編譯器會(huì)把for each語(yǔ)法結(jié)構(gòu)轉(zhuǎn)為上面的迭代器的結(jié)構(gòu)。這種方式可以遍歷所有實(shí)現(xiàn)了Iterable接口的結(jié)構(gòu)。

Iterable

Iterable只包含一個(gè)iterator抽象方法

public interface Iterable<T> {
    
    Iterator<T> iterator();
    ...
}

目的是讓用戶實(shí)現(xiàn)自定義的數(shù)據(jù)結(jié)構(gòu)返回一個(gè)實(shí)現(xiàn)了Iterator接口的對(duì)象,我們看到ArrayList的實(shí)現(xiàn)如下:

public Iterator<E> iterator() {
    return new Itr();
}

其中Itr是一個(gè)內(nèi)部類,定義在ArrayList中,并實(shí)現(xiàn)了Iterator接口。

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer<? super E> consumer) {
        Objects.requireNonNull(consumer);
        final int size = ArrayList.this.size;
        int i = cursor;
        if (i >= size) {
            return;
        }
        final Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length) {
            throw new ConcurrentModificationException();
        }
        while (i != size && modCount == expectedModCount) {
            consumer.accept((E) elementData[i++]);
        }
        // update once at end of iteration to reduce heap write traffic
        cursor = i;
        lastRet = i - 1;
        checkForComodification();
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

最重要的是Java SE8中不寫循環(huán)而直接使用forEachRemaining方法就可以使用Lambda表達(dá)式處理每個(gè)元素:

strings.iterator().forEachRemaining(e-> System.out.println(e));

同時(shí)也可是使用Iterable接口中的forEach方法來(lái)遍歷:

strings.forEach(e-> System.out.println(e));
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 概述 Java集合框架由Java類庫(kù)的一系列接口、抽象類以及具體實(shí)現(xiàn)類組成。我們這里所說(shuō)的集合就是把一組對(duì)象組織到...
    absfree閱讀 1,279評(píng)論 0 10
  • title: java集合框架學(xué)習(xí)總結(jié) tags:集合框架 categories:總結(jié) date: 2017-03...
    行徑行閱讀 1,708評(píng)論 0 2
  • 前言:一名iOS開發(fā)工程師,正在學(xué)習(xí)Android開發(fā),期待各路大神指點(diǎn)和學(xué)習(xí)交流.學(xué)習(xí)交流討論及資料獲取請(qǐng)關(guān)注:...
    極客James閱讀 4,450評(píng)論 0 5
  • 集合框架體系概述 為什么出現(xiàn)集合類?方便多個(gè)對(duì)象的操作,就對(duì)對(duì)象進(jìn)行存儲(chǔ),集合就是存儲(chǔ)對(duì)象最常用的一種方法. 數(shù)組...
    acc8226閱讀 791評(píng)論 0 1
  • 第二名 現(xiàn)在小學(xué)語(yǔ)文太難了,看他們的一道作業(yè)題: 要求:把以下四句話用關(guān)聯(lián)詞連接: (1)李姐姐癱瘓了; (2)李...
    享受福袋閱讀 349評(píng)論 0 1