jdk 包版本:jdk1.8.0_111
集合的迭代器
目前在集合中常用的迭代器有三种:Iterator,Iterable 和 ListIterator。
Iterator 接口
Iterator自 jdk 1.2 出现,取代了 Java 集合框架原来的 Enumeration 接口,两者的区别主要体现在:
Iterator允许调用方在迭代访问的过程中要友好的语法进行 remove 操作;Iterator对方法名进行了优化。
在早期的 jdk 版本里,遍历集合只能通过Iterator迭代器进行操作。
目前常用的 jdk 1.8 版本的Iterator接口源码定义如下:
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (has.next())
action.accept(next());
}
}
Iterator 接口提供了四个 API:
- hasNext( ):判断集合中是否存在下一个元素。
- next( ):返回集合中的下一个对象,并且将访问指针向后移动一位。
- remove( ):删除集合中上一次调用 next( ) 方法返回的对象,且每次调用 next( ) 后,只能都调用一次 remove( ) 方法,否则会抛出
IllegalStateException异常。接口默认实现抛出UnsupportedOperationException,表示不能进行删除操作。 - forEachRemaining(Consumer<? super E> action):对每个可访问的元素执行传入的行为方法,直至所有元素都执行完毕或者某一次执行过程中抛出了异常。这是自 jdk 1.8 后出现的新方法。
上述的最后一个方法中传入了Consumer接口的动作,这个接口也是 jdk 1.8 才出现的接口,是一个函数式接口,提供了一下的接口方法:
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consemer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); }
}
}
源码注释对这个接口的说明是:
Represents an operation that accepts a single input argument and returns no result. Unlike most other functional interfaces, Consumer is expected to operate via side-effects.
This is a functional interface whose functional method is accept(Object).
直译过来就是,这个接口表示一个接收单个入参且不返回结果的操作。与其他大多数函数式接口不同的是,它期望通过副作用进行操作。这是一个函数式接口,其函数方法为 accept(Object)。
在这里副作用的含义是,函数或者表达式具有修改基本变量的行为。由于Comsumer接口只接收一个入参,且接口方法不返回任何结果,对入参执行方法后,基本都会改变入参原来的值。如果入参的值没有改变的情况,我们则称之为无副作用。总的来说,其实Comsumer接口方法完成的就是一个赋值操作。
Iterable 接口
Iterable自 jdk 1.5 出现,接口内提供了一个 Iterator( ) 方法返回迭代器,实现该接口的集合依然可以使用迭代器对集合内的对象进行遍历操作。自 jdk 1.8 后,Iterable接口增加的两个新方法forEach和spliterator。具体方法如下:
public interface Iterable<T> {
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);
}
}
forEach方法是一个增强型的 for 循环,遍历每一个对象且对之执行传入的函数操作,当传入方法为空时会抛出空指针异常。spliterator方法返回一个可拆分的迭代器,同样可用于遍历数据源中的元素,但它是为了并行执行而设计的。在具体业务场景使用时,常常都会覆写这个方法的实现,以保证更优的实现性能。
ListIterator 接口
ListIterator接口自 jdk 1.2 出现,继承了Iterator接口,且仅存在于 List 集合当中。它提供方法返回一个允许双向遍历的迭代器,大多数方法与Iterator接口的一样。不过需要注意的是,ListIterator迭代器中的指针不是只向某一个特定元素的,而是指向前后两个元素之间的位置。这样设计是为了便于获取 previous( ) 和 next( ) 返回的元素,也就是说它不存在当前元素的这个概念。
源码中包括的方法如下:
public interface ListIterator<E> extends Iterator<E> {
boolean hasNext();
E next();
boolean hasPrevious();
E previous();
int nextIndex();
int previousIndex();
void remove();
void set(E e);
void add(E e);
}
Iterator 接口提供了四类 API:
- hasNext( ),hasPrevious( ):判断正向或者反向遍历是否存在下一个元素。
- next( ),previous( ):获取正向或者反向遍历的下一个元素,不存在下一个元素则抛出
NoSuchElementException异常。 - nextIndex( ),previousIndex( ):获取正向或者反向遍历下一个元素的下标值,到达边缘则返回 -1。
- remove( ),set(E e),add(E e):修改操作的方法。remove( ) 删除上一次调用 next( ) 或者 previous( ) 方法时返回的元素,只能执行一次,且必须不能在执行 add( ) 方法之后。set(E e) 方法类似,同样必须不能在调用 remove( ) 或者 add( ) 方法后执行。add( ) 方法将在当前指针位置插入新元素,插入后指针位于新元素之后,next( ) 返回的元素之前。
本文介绍了Java集合框架中的迭代器接口,包括Iterator、Iterable和ListIterator。Iterator自jdk1.2起取代Enumeration,提供hasNext()、next()和remove()等方法。jdk1.8新增的forEachRemaining()方法支持Consumer接口。Iterable自jdk1.5引入,提供forEach()和spliterator()方法。ListIterator则允许双向遍历,常见于List集合。这些迭代器接口在遍历和操作集合元素时发挥关键作用。
321

被折叠的 条评论
为什么被折叠?



