扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
这篇文章主要讲解了如何实现Java Iterator接口,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。
为南漳等地区用户提供了全套网页设计制作服务,及南漳网站建设行业解决方案。主营业务为成都网站制作、成都网站建设、南漳网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
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: * *
This interface is a member of the
*
* Java Collections Framework.
*
* @param The default implementation behaves as if:
* {@code
* while (hasNext())
* action.accept(next());
* }
*
* @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接口的关系/Iterator接口在Java集合库中的作用
Iterator接口是Java集合框架的一部分,被用于替代原有的Enumeration接口。(“Iterator”比“Enumeration”更简短、表意更清晰、功能更多,具体的信息下面Enumeration接口的注解中说的挺清楚,且Enumeration注解中也建议编程人员改用Iterator接口)
Java类库中,集合类的基本接口是Collection接口,而Collection接口实现了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 *nextElement
method return successive elements of the * series. ** For example, to print all elements of a Vector<E> v: *
* for (Enumeration<E> e = v.elements(); e.hasMoreElements();) * System.out.println(e.nextElement());** 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 *
SequenceInputStream
. ** 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
{ /** * Tests if this enumeration contains more elements. * * @return true
if and only if this enumeration object * contains at least one more element to provide; *false
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()方法的关系
hasNext()方法:判断是否还有元素可以进行迭代;
next()方法:迭代元素;
remove()方法:
/** * Remove from the underlying collection the last element returned by this iterator *(optional operation). * 移除当前迭代器上一次从基础集合中迭代的元素(可选操作) * * This method can be called only once per call to next(). * 调用remove()方法前必须先调用next()方法,调用完一次remove()方法后想要再次调用remove()方法, * 必须先调用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. * 如果在迭代进行过程中修改了基础集合,则迭代器的行为是不确定的。 */ public static void main(String[] args) { CollectionstringCollection = new ArrayList<>(); stringCollection.add("Hello"); stringCollection.add("World"); stringCollection.add("!"); Iterator 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 }
三者关系:调用remove()方法前必须先调用next()方法,调用next()方法前最好先调用hasNext()方法。
3.具体实现类
AbstractList类中定义了一个实现了Iterator接口的内部类:
private class Itr implements Iterator{ /** * 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;//最近一次调用next()方法返回的元素的下标。 cursor = i + 1;//下一次调用next()方法返回的元素的下标。 return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove() { if (lastRet < 0) throw new IllegalStateException();//所以,调用remove()前必须先调用next() checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--;//因为移除了一个元素 lastRet = -1;//所以,不能连续调用两次remove()方法 expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
看完上面的代码,我对modCount、expectedModCount变量以及checkForComodification()方法的作用比较好奇,所以尝试着去搞清楚。
先来看modeCount变量,这个变量被声明在内部类的外部:
public abstract class AbstractListextends AbstractCollection implements List { /** * The number of times this list has been structurally modified. * 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. * 用于表示该列表发生结构性修改的次数。结构性修改是指*更改列表的大小*或*以其他 * 方式干扰列表*,即正在进行的迭代可能会产生错误的结果。 * * 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 * fail-fast behavior, rather than non-deterministic behavior in * the face of concurrent modification during iteration. * 设计者认为,与其因为基本集合被并发修改从而使迭代产生不确定行为,不如尽早给出错误。 * *
Use of this field by subclasses is optional. 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. * 是否使用应需求决定。 */ protected transient int modCount = 0; }
看完上面的源码注解,已经大概能够知道modCount、expectedModCount以及checkForComodification()的作用了。
假如把基础集合当作一个银行账号,基础集合中的元素表示存款。那么modCount就相当于银行为每个账号做的消费记录,expectedModCount就相当于是账号持有人自己做的一份消费记录,一般银行和账号持有人自己做的消费记录都不会出错。
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
一旦银行那边的消费记录和自己手里的那份消费记录对不上,肯定是账号被盗用了。
看完上述内容,是不是对如何实现Java Iterator接口有进一步的了解,如果还想学习更多内容,欢迎关注创新互联行业资讯频道。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流