Iterator和Iterable解析


之前一直搞不清楚Iterator和Iterable到底有什么關(guān)系,它們的區(qū)別是什么,今天查看Java集合類源碼才發(fā)現(xiàn)其中的名堂,接下來給大家講講我的分析與理解。

Iterable接口

Iterable是接口,Iterable是1.5引入的新特性,Iterator是1.2就有了,二者都是為了迭代造作,Iterable只是包裝了Iterator,從而允許實現(xiàn)此接口的對象成為foreach語句的目標,而且這樣的話,更方便以后的擴展。

public interface Iterable<T> {
    /**
     * Returns an iterator over elements of type {@code T}.
     *
     * @return an Iterator.
     */
    Iterator<T> iterator();
   
    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);
    }
}

Java集合Collection接口就擴展了Iterable接口。實現(xiàn)Iterable接口的那些類就可以擁有增強的for循環(huán),該循環(huán)施于這些類之上以觀察他們所有的項。


public interface Collection<E> extends Iterable<E> {
    
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    boolean add(E e);
    boolean remove(Object o);
    boolean containsAll(Collection<?> c);
    boolean removeAll(Collection<?> c);
    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;
    }
    boolean retainAll(Collection<?> c);
    void clear();
    boolean equals(Object o);
    int hashCode();
    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}

實現(xiàn)Iterable接口的集合必須提供一個稱為itrator的方法,該方法又返回一個Iterator類型的對象。所以例如List集合類,Set類,他們實現(xiàn)了Collection接口,自然實現(xiàn)了Iterable接口,在其源碼中有具體的iterator方法,例如:ArraryList類中,它實現(xiàn)了List接口

    public Iterator<E> iterator() {
        return new Itr();
    }
    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();
            }
        }
        ...

Iterator迭代器

Iterator接口的思路是,通過iterator方法,每個集合均可創(chuàng)建并返回給客戶一個實現(xiàn)Iterator接口的對象。

public interface Iterator<E> {
    boolean hasNext();
    T next();
    void remove();
}

Iterator一般用于簡單遍歷集合中的元素。而Iterator還有一個有用的方法叫做remove()方法,相對于Collection中的remove而言,它具有更多的優(yōu)點。

對比Collection中remove方法和Iterator中remove方法

  • 抽象類AbstractCollection(實現(xiàn)了Collection接口)的remove方法
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;
    }

Collection的remove方法必須首先找出要被刪除的項,開銷較大。

  • Iterator中的remove方法
 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 void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);//remove()方法下面有給出
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
    }
 }

以上是ArrayList中其實現(xiàn)Iterator接口的內(nèi)部類中remove方法,可能其中有些變量你看不懂,需要聯(lián)系整個源碼才能夠明白它大體的意思。

以下是ArrayList重寫AbstractList中remove()方法。

public E remove(int index) {

        rangeCheck(index);//檢查是否越界

        modCount++;
        E oldValue = elementData(index);//得到要刪除的元素

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);//復(fù)制數(shù)組
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;//返回要刪除的元素
    }

不難看出Iterator的remove方法并沒有一個一個比較找出所要刪除的項,而是知道要刪除項的準確位置,那么刪除它的開銷就小很多。


使用Iterator的基本法則

如果對正在被迭代的集合進行結(jié)構(gòu)上的改變(即對集合使用add,remove或clear方法),那么迭代器就不再合法(并且在其后使用該迭代器時將會有ConcurrentModificationException異常被拋出)。然而,如果迭代器調(diào)用了它自己的remove方法,那這個迭代器仍然是合法的,所以這是我們有時候更愿意使用迭代器的remove方法的第二個原因。

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

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

  • 1.Java集合框架是什么?說出一些集合框架的優(yōu)點? 每種編程語言中都有集合,最初的Java版本包含幾種集合類:V...
    hutuxiaogui閱讀 681評論 0 10
  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX閱讀 893評論 0 1
  • 1 場景問題# 1.1 工資表數(shù)據(jù)的整合## 考慮這樣一個實際應(yīng)用:整合工資表數(shù)據(jù)。 這個項目的背景是這樣的,項目...
    七寸知架構(gòu)閱讀 2,581評論 0 53
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,991評論 19 139
  • 頭馬圈是一群愛學(xué)習(xí)的人的天地,我們樂此不疲的參加各種活動。每當你付出一點,還能得到十點反饋,多值的交易。 為了增加...
    Tina新星閱讀 167評論 0 1