这是否打破了?Iterator
哈哈
Java强加了两个“契约”。第一个协定是 Java 接口本身,它声明了 3 个方法:、 和 。实现此接口的任何类都必须定义这些方法。Iterator
hasNext()
next()
remove()
Iterator
第二个协定定义了迭代器
的行为:
hasNext()
[...] 如果迭代具有更多元素,则返回 true。[...] 返回迭代中的下一个元素 [,如果迭代没有更多元素,则抛出] 。next()
NoSuchElementException
这就是整个合同。
确实,如果底层是高级的,它可能会弄乱您的和/或.或者,调用和/或在错误的点可能会弄乱迭代。但是,如果使用得当,例如在上面的示例代码中,它可以正常工作并大大简化代码。您只需要记录迭代器的正确用法。XMLStreamReader
BoxIterator
DrawerIterator
BoxIterator.next()
DrawerIterator.next()
作为一个具体示例,Scanner
类实现了 ,但还有许多其他方法可以推进底层流。如果存在由该类强加的更强的契约,那么该类本身将违反它。Iterator<String>
Iterator
Scanner
正如伊万在评论中指出的那样,不应该是类型。你真的应该有:boxList
class BoxIterator implements Iterator<Box>, Iterable<Box>
class BoxList implements Iterable<Box> { ... }
class BoxIterator implements Iterator<Box> { ... }
BoxList boxList = ...;
for (Box box : boxList) {
for (Drawer drawer : box) {
drawer.getId()
}
}
虽然让一个类同时实现两者,并且对于您的用例来说在技术上没有错误,但它可能会导致混淆。Iterable
Iterator
在另一个上下文中考虑此代码:
List<Box> boxList = Arrays.asList(box1, box2, box3, box4);
for(Box box : boxList) {
// Do something
}
for(Box box : boxList) {
// Do some more stuff
}
这里调用两次,以创建两个单独的实例,用于迭代两次框列表。由于 可以多次迭代 ,因此每次迭代都需要一个新的迭代器实例。boxList.iterator()
Iterator<Box>
boxList
在代码中:
BoxIterator boxList = new BoxIterator(xml_stream);
for (Box box : boxList) {
for (Drawer drawer : box) {
drawer.getId();
}
}
由于您正在迭代流,因此无法(不倒带流或存储提取的对象)再次循环访问相同的节点。不需要第二个类/对象;同一个对象可以同时充当迭代器和迭代器...这为您节省了一个类/对象。
话虽如此,过早优化是万恶之源。一个类/对象的节省不值得可能的混淆;您应该拆分为 、 和 。BoxIterator
BoxList implements Iterable<Box>
BoxIterator implements Iterator<Box>