Java Iterator接口實(shí)現(xiàn)代碼解析
Iterator接口
源代碼
package java.util; import java.util.function.Consumer; /** * An iterator over a collection. {@code Iterator} takes the place of * {@link Enumeration} in the Java Collections Framework. Iterators * differ from enumerations in two ways: * * <ul> * <li> Iterators allow the caller to remove elements from the * underlying collection during the iteration with well-defined * semantics. * <li> Method names have been improved. * </ul> * * <p>This interface is a member of the * <a href="{@docRoot}/../technotes/guides/collections/index.html" rel="external nofollow" > * Java Collections Framework</a>. * * @param <E> the type of elements returned by this iterator * * @author Josh Bloch * @see Collection * @see ListIterator * @see Iterable * @since 1.2 */ public interface Iterator<E> { /** * Returns {@code true} if the iteration has more elements. * (In other words, returns {@code true} if {@link #next} would * return an element rather than throwing an exception.) * * @return {@code true} if the iteration has more elements */ boolean hasNext(); /** * Returns the next element in the iteration. * * @return the next element in the iteration * @throws NoSuchElementException if the iteration has no more elements */ E next(); /** * Removes from the underlying collection the last element returned * by this iterator (optional operation). This method can be called * only once per call to {@link #next}. The behavior of an iterator * is unspecified if the underlying collection is modified while the * iteration is in progress in any way other than by calling this * method. * * @implSpec * The default implementation throws an instance of * {@link UnsupportedOperationException} and performs no other action. * * @throws UnsupportedOperationException if the {@code remove} * operation is not supported by this iterator * * @throws IllegalStateException if the {@code next} method has not * yet been called, or the {@code remove} method has already * been called after the last call to the {@code next} * method */ default void remove() { throw new UnsupportedOperationException("remove"); } /** * Performs the given action for each remaining element until all elements * have been processed or the action throws an exception. Actions are * performed in the order of iteration, if that order is specified. * Exceptions thrown by the action are relayed to the caller. * * @implSpec * <p>The default implementation behaves as if: * <pre>{@code * while (hasNext()) * action.accept(next()); * }</pre> * * @param action The action to be performed for each element * @throws NullPointerException if the specified action is null * @since 1.8 */ default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) action.accept(next()); } }
閱讀筆記
1. Iterator接口與Enumeration接口的關(guān)系/Iterator接口在Java集合庫中的作用
Iterator接口是Java集合框架的一部分,被用于替代原有的Enumeration接口。(“Iterator”比“Enumeration”更簡短、表意更清晰、功能更多,具體的信息下面Enumeration接口的注解中說的挺清楚,且Enumeration注解中也建議編程人員改用Iterator接口)
Java類庫中,集合類的基本接口是Collection接口,而Collection接口實(shí)現(xiàn)了Iterable接口,Iterable接口中有一個iterator()方法用于獲取Iterator對象。
package java.util; /** * An object that implements the Enumeration interface generates a * series of elements, one at a time. Successive calls to the * <code>nextElement</code> method return successive elements of the * series. * <p> * For example, to print all elements of a <tt>Vector<E></tt> <i>v</i>: * <pre> * for (Enumeration<E> e = v.elements(); e.hasMoreElements();) * System.out.println(e.nextElement());</pre> * <p> * Methods are provided to enumerate through the elements of a * vector, the keys of a hashtable, and the values in a hashtable. * Enumerations are also used to specify the input streams to a * <code>SequenceInputStream</code>. * <p> * NOTE: The functionality of this interface is duplicated by the Iterator * interface. In addition, Iterator adds an optional remove operation, and * has shorter method names. New implementations should consider using * Iterator in preference to Enumeration. * * @see java.util.Iterator * @see java.io.SequenceInputStream * @see java.util.Enumeration#nextElement() * @see java.util.Hashtable * @see java.util.Hashtable#elements() * @see java.util.Hashtable#keys() * @see java.util.Vector * @see java.util.Vector#elements() * * @author Lee Boynton * @since JDK1.0 */ public interface Enumeration<E> { /** * Tests if this enumeration contains more elements. * * @return <code>true</code> if and only if this enumeration object * contains at least one more element to provide; * <code>false</code> otherwise. */ boolean hasMoreElements(); /** * Returns the next element of this enumeration if this enumeration * object has at least one more element to provide. * * @return the next element of this enumeration. * @exception NoSuchElementException if no more elements exist. */ E nextElement(); }
2.hasNext()、next()、remove()方法的關(guān)系
hasNext()方法:判斷是否還有元素可以進(jìn)行迭代;
next()方法:迭代元素;
remove()方法:
/** * Remove from the underlying collection the last element returned by this iterator *(optional operation). * 移除當(dāng)前迭代器上一次從基礎(chǔ)集合中迭代的元素(可選操作) * * This method can be called only once per call to next(). * 調(diào)用remove()方法前必須先調(diào)用next()方法,調(diào)用完一次remove()方法后想要再次調(diào)用remove()方法, * 必須先調(diào)用next()方法。 * * The behavior of an iterator is unspecified if the underlying collection is modifyed while * the iteration is in progress is any way other than by call this method. * 如果在迭代進(jìn)行過程中修改了基礎(chǔ)集合,則迭代器的行為是不確定的。 */ public static void main(String[] args) { Collection<String> stringCollection = new ArrayList<>(); stringCollection.add("Hello"); stringCollection.add("World"); stringCollection.add("!"); Iterator<String> stringIterator = stringCollection.iterator(); stringIterator.next(); stringIterator.remove();//OK } public static void main(String[] args) { ...... stringIterator.next(); stringCollection.add("abc");//基本集合被改變 stringIterator.remove();//ERROR - java.util.ConcurrentModificationException } public static void main(String[] args) { ...... stringIterator.next(); stringCollection.add("abc");//基本集合被改變 stringIterator.next();//ERROR - java.util.ConcurrentModificationException } public static void main(String[] args) { ...... stringIterator.next(); stringCollection.add("abc");//基本集合改變 stringIterator = stringCollection.iterator();//重新獲取迭代器 stringIterator.next();//OK stringIterator.remove();//OK }
三者關(guān)系:調(diào)用remove()方法前必須先調(diào)用next()方法,調(diào)用next()方法前最好先調(diào)用hasNext()方法。
3.具體實(shí)現(xiàn)類
AbstractList類中定義了一個實(shí)現(xiàn)了Iterator接口的內(nèi)部類:
private class Itr implements Iterator<E> { /** * Index of element to be returned by subsequent call to next. */ int cursor = 0; /** * Index of element returned by most recent call to next or * previous. Reset to -1 if this element is deleted by a call * to remove. */ int lastRet = -1; /** * The modCount value that the iterator believes that the backing * List should have. If this expectation is violated, the iterator * has detected concurrent modification. */ int expectedModCount = modCount; public boolean hasNext() { return cursor != size(); } public E next() { checkForComodification(); try { int i = cursor; E next = get(i); lastRet = i;//最近一次調(diào)用next()方法返回的元素的下標(biāo)。 cursor = i + 1;//下一次調(diào)用next()方法返回的元素的下標(biāo)。 return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove() { if (lastRet < 0) throw new IllegalStateException();//所以,調(diào)用remove()前必須先調(diào)用next() checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--;//因?yàn)橐瞥艘粋€元素 lastRet = -1;//所以,不能連續(xù)調(diào)用兩次remove()方法 expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
看完上面的代碼,我對modCount、expectedModCount變量以及checkForComodification()方法的作用比較好奇,所以嘗試著去搞清楚。
先來看modeCount變量,這個變量被聲明在內(nèi)部類的外部:
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { /** * The number of times this list has been <i>structurally modified</i>. * Structural modifications are those that change the size of the * list, or otherwise perturb it in such a fashion that iterations in * progress may yield incorrect results. * 用于表示該列表發(fā)生結(jié)構(gòu)性修改的次數(shù)。結(jié)構(gòu)性修改是指*更改列表的大小*或*以其他 * 方式干擾列表*,即正在進(jìn)行的迭代可能會產(chǎn)生錯誤的結(jié)果。 * * <p>This field is used by the iterator and list iterator implementation * returned by the {@code iterator} and {@code listIterator} methods. * If the value of this field changes unexpectedly, the iterator (or list * iterator) will throw a {@code ConcurrentModificationException} in * response to the {@code next}, {@code remove}, {@code previous}, * {@code set} or {@code add} operations. This provides * <i>fail-fast</i> behavior, rather than non-deterministic behavior in * the face of concurrent modification during iteration. * 設(shè)計(jì)者認(rèn)為,與其因?yàn)榛炯媳徊l(fā)修改從而使迭代產(chǎn)生不確定行為,不如盡早給出錯誤。 * * <p><b>Use of this field by subclasses is optional.</b> If a subclass * wishes to provide fail-fast iterators (and list iterators), then it * merely has to increment this field in its {@code add(int, E)} and * {@code remove(int)} methods (and any other methods that it overrides * that result in structural modifications to the list). A single call to * {@code add(int, E)} or {@code remove(int)} must add no more than * one to this field, or the iterators (and list iterators) will throw * bogus {@code ConcurrentModificationExceptions}. If an implementation * does not wish to provide fail-fast iterators, this field may be * ignored. * 是否使用應(yīng)需求決定。 */ protected transient int modCount = 0; }
看完上面的源碼注解,已經(jīng)大概能夠知道m(xù)odCount、expectedModCount以及checkForComodification()的作用了。
假如把基礎(chǔ)集合當(dāng)作一個銀行賬號,基礎(chǔ)集合中的元素表示存款。那么modCount就相當(dāng)于銀行為每個賬號做的消費(fèi)記錄,expectedModCount就相當(dāng)于是賬號持有人自己做的一份消費(fèi)記錄,一般銀行和賬號持有人自己做的消費(fèi)記錄都不會出錯。
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
一旦銀行那邊的消費(fèi)記錄和自己手里的那份消費(fèi)記錄對不上,肯定是賬號被盜用了。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java9版本特性資源自動關(guān)閉的語法增強(qiáng)
這篇文章主要為大家介紹了java9版本特性資源自動關(guān)閉的語法增強(qiáng)的詳細(xì)使用說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03spring整合redis消息監(jiān)聽通知使用的實(shí)現(xiàn)示例
在電商系統(tǒng)中,秒殺,搶購,紅包優(yōu)惠卷等操作,一般都會設(shè)置時(shí)間限制,本文主要介紹了spring整合redis消息監(jiān)聽通知使用,具有一定的參考價(jià)值,感興趣的可以了解一下2021-12-12基于Springboot疫苗接種行程管理系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
本文主要介紹了基于Springboot實(shí)現(xiàn)的疫苗接種行程管理系統(tǒng)的示例代碼,系統(tǒng)主要實(shí)現(xiàn)個人疫苗接種管理、行程管理、病史管理、風(fēng)險(xiǎn)地區(qū)管理、核酸檢測報(bào)告結(jié)果上報(bào)、疫情新聞管理等功能,需要的可以參考一下2022-03-03Java SpringBoot實(shí)現(xiàn)AOP
AOP包括連接點(diǎn)(JoinPoint)、切入點(diǎn)(Pointcut)、增強(qiáng)(Advisor)、切面(Aspect)、AOP代理(AOP Proxy),具體的方法和類型下面文章會舉例說明,感興趣的小伙伴和小編一起閱讀全文吧2021-09-09Java實(shí)現(xiàn)樹形List與扁平List互轉(zhuǎn)的示例代碼
在平時(shí)的開發(fā)中,我們時(shí)常會遇到需要將"樹形List"與"扁平List"互轉(zhuǎn)的情況,本文為大家整理了Java實(shí)現(xiàn)樹形List與扁平List互轉(zhuǎn)的示例代碼,希望對大家有所幫助2023-05-05