我的问题是:是否可以仅通过实施Iterator
来浏览容器,即不实施Iterable
?
是否可以这样做:
//From somewhere
Container c = new Container();
//I add elements to the list in the c object.
for(String s : c){
//Warning: It is not applicable for this expression...
}
class Container implements Iterator<String>{
//Here I implement a single linked list
//Here I implement all of the methods of Iterator
}
答案 0 :(得分:4)
Iterable
和Iterator
之间存在逻辑差异。
Iterable
是可以迭代的集合或数据结构。它是一个数据持有者。
Iterator
是定义迭代逻辑的对象(以什么方式和顺序循环通过Iterable
的元素)。它(并且大多数时候应该)可以与数据结构或集合的逻辑分开。目的是能够为同一Iterator
定义多个Iterable
实现
我错过的重要点,但在其他答案中出现,是保持循环状态远离可迭代对象。这允许同时循环通过相同的集合,因为每个循环将使用单独的迭代器实例。
一个简单的例子是将两个迭代器写入ArrayList
,一个循环向前,另一个向后循环。您只需要在现有类(Iterator
)上创建ArrayList
实现,而无需修改后者。因此,可以只实现一个迭代器。
然而,Java语言中的for
循环结构设计用于迭代。代码:
for (Object o : collecton) {
...
}
由编译器翻译为:
Iterator i = collection.iterator();
while (i.hasNext()) {
....
}
因此,迭代器本身不能以标准方式使用for
循环。或者你可以像这样使用它:
for (Iterator i = collection.iterator(); i.hasNext(); ) {
Object current = i.next();
....
}
答案 1 :(得分:4)
如何在容器上连续两次迭代:
通过直接实现Iterator
,由于变量的Iterator将由所有客户共享,因此您将无法在您的集合中多次迭代...
通过定义方法Iterator
:(与AbstractList
上的方法类似):
public Iterator iterator(){ return new Itr(); //每次新实例 }
每次创建Iterator
的新实例允许您根据需要迭代多次。 (当然,最好不要同时)。
此外,它避免违反单一责任原则,因为迭代容器的方式代表了另一个目标而不是“定义”容器。
答案 2 :(得分:4)
即使这种设计只是荒谬,只是为了娱乐你的问题,你可以这样写:
public class Container implements Iterable<String>, Iterator<String> {
@Override public Iterator<String> iterator() { return this; }
... everything else you envision for your class ...
}
然后你就可以使用
了for (String s : container)
你可以把它写成一个学习经历,但我强烈建议你永远不要在一个真实的项目上尝试。反对它的主要原因是期望iterator
方法总是返回一个新的,独立的迭代器,而这个实现实现了相反的结果。举一个具体的例子,假设某人需要自己迭代容器的笛卡尔积:
for (String s1 : container)
for (String s2 : container)
processPair(s1, s2);
每个Java程序员都会告诉您,毫无疑问,processPair
将从容器中调用每个可能的对。他们会从你的班级中看到的行为会使他们的头脑旋转。如果生产中的一个错误被追溯到这个实现,那么你的队友会...让我们说他们不会欣赏它。
答案 3 :(得分:3)
要使用enhanced for-loop
(a.k.a花式for-loop),您必须实施Iterable而不是Iterator
当然你可以实现Iterator
,在这种情况下你的容器将是Iterator
public class Cont<T> implements Iterator<T> {
@Override
public boolean hasNext() {
// TODO implment
return false;
}
@Override
public T next() {
// TODO implment
return null;
}
@Override
public void remove() {
// TODO implment
}
}
你可以这样使用它:
public static void main(String... args) {
Cont cont = new Cont<SomeType>();
while(cont.hasNext()) {
SomeType obj = cont.next();
}
}
通常的情况是Implment Iterable
,因此您可以使用所有可用的语言功能。如果要对Collection
进行编码,或者希望在其某些方法中包含某些逻辑,请实现Iterator,例如lazy loading
方法中的next()
。
答案 4 :(得分:3)
即使您拥有class implements Iterator<T>
才能获得iterator()
,您必须实施iterable
并返回iterator
public class MyCollection<E> implements Iterable<E>{
public Iterator<E> iterator() {
return new MyIterator<E>();
}
}
以下是MyIterator类的相应实现框架:
public class MyIterator <T> implements Iterator<T> {
public boolean hasNext() {
//implement...
}
public T next() {
//implement...;
}
public void remove() {
//implement... if supported.
}
}
答案 5 :(得分:1)
如果您想使用简单的 for-each 语句 - 否。您需要使用Iterator<E>
方法从Iterable<E>
对象调用iterator()
对象。