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集合庫(kù)中的作用
Iterator接口是Java集合框架的一部分,被用于替代原有的Enumeration接口。(“Iterator”比“Enumeration”更簡(jiǎn)短、表意更清晰、功能更多,具體的信息下面Enumeration接口的注解中說(shuō)的挺清楚,且Enumeration注解中也建議編程人員改用Iterator接口)
Java類庫(kù)中,集合類的基本接口是Collection接口,而Collection接口實(shí)現(xiàn)了Iterable接口,Iterable接口中有一個(gè)iterator()方法用于獲取Iterator對(duì)象。
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)行過(guò)程中修改了基礎(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類中定義了一個(gè)實(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)橐瞥艘粋€(gè)元素
lastRet = -1;//所以,不能連續(xù)調(diào)用兩次remove()方法
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
看完上面的代碼,我對(duì)modCount、expectedModCount變量以及checkForComodification()方法的作用比較好奇,所以嘗試著去搞清楚。
先來(lái)看modeCount變量,這個(gè)變量被聲明在內(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)行的迭代可能會(huì)產(chǎn)生錯(cuò)誤的結(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)生不確定行為,不如盡早給出錯(cuò)誤。
*
* <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)作一個(gè)銀行賬號(hào),基礎(chǔ)集合中的元素表示存款。那么modCount就相當(dāng)于銀行為每個(gè)賬號(hào)做的消費(fèi)記錄,expectedModCount就相當(dāng)于是賬號(hào)持有人自己做的一份消費(fèi)記錄,一般銀行和賬號(hào)持有人自己做的消費(fèi)記錄都不會(huì)出錯(cuò)。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
一旦銀行那邊的消費(fèi)記錄和自己手里的那份消費(fèi)記錄對(duì)不上,肯定是賬號(hào)被盜用了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis實(shí)現(xiàn)自定義類型轉(zhuǎn)換器TypeHandler的方法
Mybatis實(shí)現(xiàn)自定義的轉(zhuǎn)換器非常的簡(jiǎn)單,只需要三步就可以實(shí)現(xiàn)自定義類型轉(zhuǎn)換器TypeHandler,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看下吧2016-07-07
Java找出兩個(gè)大數(shù)據(jù)量List集合中的不同元素的方法總結(jié)
本文將帶大家了解如何快速的找出兩個(gè)相似度非常高的List集合里的不同元素。主要通過(guò)Java API、List集合雙層遍歷比較不同、借助Map集合查找三種方式,需要的可以參考一下2022-10-10
SpringBoot?多環(huán)境打包最佳實(shí)踐記錄
SpringBoot通過(guò)配置多環(huán)境文件和在打包時(shí)指定激活的環(huán)境,實(shí)現(xiàn)多環(huán)境打包與部署,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-11-11
Springboot 如何關(guān)閉自動(dòng)配置
這篇文章主要介紹了Springboot 如何關(guān)閉自動(dòng)配置的操作,具有很好的開(kāi)車價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09

