一家之言 姑妄言之 絮絮叨叨 不足为训
Iterator接口注释翻译:
集合上的迭代器。迭代器在Java集合框架中代替了枚举。迭代器与枚举有两个不同之处:
1.迭代器允许调用者使用定义良好的语义在迭代期间从基础集合中删除元素。
2.方法名已经得到了改进。
该接口是Java集合框架的成员。
笔者废话:
这里的Iterator
译为迭代器,那么对于我来说,其实这就是个循环对象而已。它作为一个接口,也就是一个对象,其工作就是遍历集合中的对象,当然,这些集合对象需要去实现它。你可以理解它为for循环的变种,但是这里也仅仅表明“理解”而不是等同。
也只有实现了Iterator
接口的对象才能调用其方法,这点是毋庸置疑的。所以,我们也可以理解为Iterator
就是那些实现了它的集合本身所拥有的属性,而这个属性也规定了,我们的集合,是可以遍历的。
Iterator接口信息:
public interface Iterator<E>
我们可以清楚的看到,Iterator
是一个接口,而且这里还规定了泛型机制。而通过接口注释来看,这个泛型E就是这个迭代器返回的元素的类型。
Iterator接口方法信息:
/**
* 如果该迭代器内有更多的元素,则返回true。换句话说,如果next将返回
* 一个元素而不是抛出一个异常,则返回true
* @return 如果该迭代器内有更多的元素,则为真
*/
boolean hasNext();
这个方法意在询问当前遍历的容器中是否含有下一个元素。这里会涉及到一个指针操作,当然,我们java宣称的可是没有指针,所以,这我们可以把它称之为“指向”。一般来说,如果我们使用了某个集合的Iterator
对象后,会在这个集合的上方出现一个空值,而我们的Iterator
对象就指向这个空值。
但是需要注意的是,这个方法仅仅是询问下一个元素是否存在,此时并不移动指向位置,只有调用了next()
方法后,这个指向位置才会进行移动,即,移动到下一项。
/**
* 返回迭代器中的下一个元素。
* @return 返回迭代器中的下一个元素。
* @throws 如果迭代没有更多的元素则抛出NoSuchElementException异常
*/
E next();
这个方法是与hasNext()
方法遥相呼应的。它代表着返回迭代器中的下一个元素。一般来说,我们都会通过hasNext()
方法来判断是否有下一个元素,一旦有,那么就调用next()
方法展示(取出)这个元素。
重复上面的一段话:调用了next()
方法后,容器的指向位置会进行移动,即,移动到下一项。
/**
* 从基础集合中移除此迭代器返回的最后一个元素(可选操作)。此方法在每次
* 调用next时只能调用一次。如果在迭代过程中以调用此方法以外的任何方式
* 修改了底层集合,则迭代器的行为是未指定的。
*
* @implSpec
* 默认实现抛出UnsupportedOperationException异常,不执行其他操作。
*
* @throws 如果这个迭代器不支持删除操作则抛出
* UnsupportedOperationException异常
* @throws 如果尚未next()方法,或者在最后一次调用next()方法之后已经
* 调用了remove方法则抛出IllegalStateException异常
*/
default void remove() {
throw new UnsupportedOperationException("remove");
}
这个移除方法其实挺有的说的。
首先,我们看它的修饰符,是default
。这个default
区别于我们类里面成员属性的default
。这个是JAVA 1.8给接口新添加的特性。它表示我们可以在接口里面进行方法的默认实现。当然,这个方法也可被其实现类进行重写
其次,这个方法删除的是上一次调用了next()
方法时返回的元素。所以,这个方法必须在调用next()
方法之后才可调用,如果在next()
方法之前调用将会抛出IllegalStateException
异常。这块不是绝对啊,这块不是绝对啊,你试试ArrayList就行了。试一下只添加一个元素就开始遍历,试试啊小可爱~
再次,我们从其代码入手,会发现它默认抛出UnsupportedOperationException
异常。其本质是告诉我们,不是所有的实现类都支持Iterator
的remove()
移除操作。所以,这个方法肯定是会由其部分实现类进行重新覆写,而不是仅仅提供一个无用的方法。
这里就不再举例了,因为本身这就是一个接口,其各自的实现类都几乎重写了这个方法,所以这里即使举例也是利用其实现类。并且,各自的实现还略有差别。因此,大家可以移步我其他的集合源码分析篇章来具体查看这些示例。
/**
* 为每个剩余元素执行给定的操作,直到处理完所有元素或操作引发异常。
* 如果指定了迭代的顺序,则按照迭代的顺序执行操作。操作引发的异常将
* 被转发给调用者。
*
* @implSpec
* 默认实现的行为就像:
* 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());
}
这里是Iterator
接口中最后一个方法,它也是JAVA1.8新定义的一个方法。需要注意的是它也是一个被default
修饰符修饰的方法,即,它也是这个接口多定义具有默认实现的方法。
从方法名来看,它就是一个遍历方法,只不过它遍历的是剩余元素。那么从注释上面来看,也表明了该方法为每个剩余元素执行给定的操作,直到处理完所有元素或操作引发异常。
不过这里笔者需要表明的是,这里所谓的“剩余”其实无所谓。我们从其代码来看,它就是在遍历元素,然后对遍历出的元素做出某种操作。当然,这种操作我们还是需要具体到实现类的。
当然,根据我们文章的总意,还是需要讲解一下其代码的内部实现。
首先我们可以看到其传进来的参数是一个Consumer<? super E>
类,它是一个函数式编程接口。这个行为也表明了我们需要处理的元素必须是当前Iterator
泛型内指定类型的子类,或其本类。
接下来的代码会对其进行一次非空判断,只有通过判断才可以进行下一步操作。
当我们的参数通过了非空判断之后,剩下的,就开始了while循环进行遍历。然后对其遍历的元素进行处理。当然,这种处理之前也说过了,是需要具体到实现类的。到底做了什么处理,不能从这里得知,而应该去看其具体的实现方法。
这些具体的实现方法我会在其具体的实现类里面具体做介绍,这里还是不掺杂那么多的解释或举例。仅仅留给这个Iterator
接口一个说一是一的解析吧。
至此,我们Iterator
到此全部解析完毕(ಥ_ಥ)。