文章目录
一、概述
Iterator是 java.util 包下定义的一个接口,表示迭代器。如下:
Java 8 中已知的子接口包括:
- ListIterator
- PrimitiveIterator<T,T_CONS>
- PrimitiveIterator.OfDouble
- PrimitiveIterator.OfInt
- PrimitiveIterator.OfLong
- XMLEventReader
说明: 其中 PrimitiveIterator<T,T_CONS> 是原始迭代器,T 表示 PrimitiveIterator 返回的元素类型,T_CONS 表示 T 的原始消费者 Consumer,PrimitiveIterator.OfDouble、PrimitiveIterator.OfInt、PrimitiveIterator.OfLong 都是 PrimitiveIterator接口的静态内部接口(static interface); XMLEventReader 是 javax.xml.stream 包中定义的一个接口,这两类接口不是我们《Java Collections》的总结重点,这里重点总结下 Iterator 接口和 ListIterator 接口。
二、Iterator
从API中可以看出 Iterator 包含 4 个方法,分别是 hasNext()、next()、remove()、forEachRemaining(Consumer<? super E> action),其中 remove、forEachRemaining 方法是 default 方法,这些个方法都比较简单。
2.1 haseNext() 方法
判断当前迭代器是否包含下一个元素,如果包含返回 true,否则返回false;
/**
* 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();
2.2 next() 方法
获取当前迭代器的下一个元素,如果下一个元素为空则抛出 NoSuchElementException。
/**
* 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();
2.3 remove() 方法
移除底层集合的迭代器中的最后一个元素。
注意点:
- 这个方法需要底层的集合类重写该方法,否则执行默认方法会抛出 UnsupportedOperationException。
- 如果调用 remove() 方法之前没有被调用 next() 方法,或者调用一次next() 方法之后连续调用了2次remove() 方法,则会抛出 IllegalStateException。很好理解,因为该方法会删除当前迭代器迭代的最后一个元素,如果最后一个元素不存在,那么肯定会抛出 IllegalStateException 异常。
/**
* 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");
}
2.4 forEachRemaining(Consumer<? super E> action) 方法
遍历消费完剩余的元素,接收一个函数式接口 Consumer。这个方法也比较简单,建议经常用。
/**
* 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());
}
三、ListIterator
从 Iterator 的 API 中我们也可以得到一个很重要的信息,那就是 Iterator 只能正向操作,也只能遍历一次,遍历完一次之后就不能再遍历了。
但是 ListIterator 的 API 会告诉我们,它可以双向遍历(既可以正向遍历、也可以反向遍历),ListIterator 是一个双向迭代器,除此之外,它还可以添加和修改底层的集合元素。
说明: 从API中我们可以知道 ListIterator 继承了父接口的四个方法,除此之外,还新增了hasPrevious()、previous()、nextIndex()、previousIndex()、set(E e)、add(E e)方法。这些方法都比较简单,分别是判断迭代器是否存在上一个元素、获取上一个元素、获取下一个元素的索引、获取上一个元素的索引、设置当前迭代的元素值、添加一个元素的值,都比较简单,就不总结了。
四、迭代器的性能
在数组结构的集合中:普通for循环 > foreach ≈ iterator
在LinkList结构的集合中:普通for循环 < foreach ≈ iterator