Java中的Iterable与Iterator详解版权声明
原创在Java在这种情况下,我们可能是对的。List通过以下方式遍历集合:
List list = new ArrayList<>();
list.add(5);
list.add(23);
list.add(42);
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + ",");
}
Iterator it = list.iterator();
while (it.hasNext()) {
System.out.print(it.next() + ",");
}
for (Integer i : list) {
System.out.print(i + ",");
}
第一个是平凡for循环,第二个是迭代器遍历,第三个是for each循环后两种方法涉及Java中的iterator和iterable对象,让我们看看这两个对象之间的区别以及如何在自定义类中实现它们。for each循环。
Iterator与Iterable
iterator为Java中的迭代器对象能够。List基础依赖项迭代地遍历这样的集合。和iterable该接口定义了返回。iterator其方法是iterator在实现的同时,iterable接口的类可以支持for each循环。
iterator内部细节
jdk中Iterator该接口的主要方法如下:
public interface Iterator {
boolean hasNext();
E next();
}
iterator以上两种方法定义了迭代访问集合的方法,具体实现取决于不同的实现类,具体的集合类实现。Iterator方法来实现迭代。
可以发现,在List未在中实现Iterator接口,但实现的Iterable界面。进一步观察Iterable可以发现该接口的源代码只返回了一个。Iterator对象。
public interface Iterable {
Iterator iterator();
}
因此,我们可以使用以下方式List迭代(通过调用。iterator()方法)
Iterator it = list.iterator();
while (it.hasNext()) {
System.out.print(it.next() + ",");
}
同时,也实现了这一点。Iterable也可以使用该接口。for each循环。
for each原理
其实for each循环的内部也依赖于Iterator迭代器,只是Java提供语法糖,Java编译器会将其转换为Iterator迭代器方式遍历。我们对以下内容感兴趣for each用于反编译的循环:
for (Integer i : list) {
System.out.println(i);
}
反编译后:
Integer i;
for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){
i = (Integer)iterator.next();
}
可以看到Java的for each制作了增强环路iterator以迭代器的方式实现。
深入探讨Iterable与Iterator关系
有一个问题,为什么不直接hasNext(),next()方法放在Iterable接口,其他类可以直接实现吗?
原因是某些集合类可能有多个遍历方法来实现Iterable然后,该类可以实现多个Iterator内部类,如 LinkedList
中的 ListItr
和 DescendingIterator
这两个内部类分别实现双向遍历和逆序遍历。通过返回不同的 Iterator
实现不同的遍历方法,更加灵活。如果合并这两个接口,则无法返回不同的 Iterator
实现类。ListItr相关源代码如下:
public ListIterator listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
private class ListItr implements ListIterator {
...
ListItr(int index) {
// assert isPositionIndex(index);
next = (index == size) ? null : node(index);
nextIndex = index;
}
public boolean hasNext() {
return nextIndex < size;
}
...
如上所示,您可以调用。 list.listIterator()
方法返回iterator迭代器( list.iterator()
仅其默认实现)
DescendingIterator
源代码如下:
public Iterator descendingIterator() {
return new DescendingIterator();
}
private class DescendingIterator implements Iterator {
private final ListItr itr = new ListItr(size());
public boolean hasNext() {
return itr.hasPrevious();
}
public E next() {
return itr.previous();
}
public void remove() {
itr.remove();
}
}
它也可以通过。 list.descendingIterator()
使用迭代器。
实现您自己的迭代器。
我们现在有了一个定制类。ArrayMap,现在,如果按如下方式完成for each遍历:
ArrayMap am = new ArrayMap<>();
am.put("hello", 5);
am.put("syrups", 10);
for (String s: am) {
System.out.println(s);
}
因为我们还没有实现hashNext和next抽象方法,因此它无法被遍历。
自定义迭代器类
我们首先定制一个迭代器类实现。hashNext和next方法,以及ArrayMap对于内部类,相关代码如下:
public class KeyIterator implements Iterator {
private int ptr;
public KeyIterator() {
ptr = 0;
}
@Override
public boolean hasNext() {
return (ptr != size);
}
@Override
public K next() {
K returnItem = keys[ptr];
ptr += 1;
return returnItem;
}
}
你可以在里面看到我们next中指定的遍历规则基于ArrayMap的key值被遍历。通过上面的迭代器类,我们可以使用它。iterator该方法在外部遍历它,遍历代码如下:
ArrayMap am = new ArrayMap<>();
am.put("hello", 5);
am.put("syrups", 10);
ArrayMap.KeyIterator ami = am.new KeyIterator();
while (ami.hasNext()) {
System.out.println(ami.next());
}
如上所示,通过创建KeyIterator对象是迭代访问的(请注意外部类如何创建内部类对象)。
支持for each循环
它还不能得到支持。for each循环访问,因为我们尚未实现iterable接口,先入ArrayMap中实现Iterable接口:
public class ArrayMap implements Iterable {
private K[] keys;
private V[] values;
int size;
public ArrayMap() {
keys = (K[]) new Object[100];
values = (V[]) new Object[100];
size = 0;
}
....
}
然后重写iterator()方法,其中我们返回我们自己的迭代器对象。(iterator)
@Override
public Iterator iterator() {
return new KeyIterator();
}
请注意我们的习俗KeyIterator类必须实现Iterator接口,否则在iterator()该方法中返回的类型不匹配。
总结与感悟
(1)学会深入思考,一点一点地剥开茧,多想想为什么会实现这一点。许多问题并不像你想象的那么复杂。
(2当你遇到疑虑时,不要放弃。这是提升自我的最好机会。当你遇到困难时,你会在解决的过程中挖掘出很多相关的东西。
参考资料:
(1) CS61B
(2) for each实现原理
(3) Iterable与iterator区别 欢迎来华工作一至五年Java工程师之友加入Java群: 891219277
集团内免费Java架构学习材料(高可用性、高并发性、高性能和分布式、Jvm性能调整、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx(如多个知识点的结构)合理利用自己的每一分钟、每一秒来学习提高自己,不要再用它了"没有时间把自己的懒惰藏在思想里!趁着年轻,努力奋斗,给自己一个未来的解释!
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除