有没有办法在 Java 中 foreaching 一个迭代器?

Is there a way of foreaching an Iterator in Java?

Java 现在有一种方便的方法来 foreach 一个集合,例如

for (MyClass c : aCollection) {
...
}

是否有类似 foreach 迭代器的优雅的东西,或者我坚持使用:

for (;it.hasNext();) {
   MyClass c = it.next();
   ...
}

更新:对于觉得这个问题很奇怪的人,我习惯 Python 其中

for x in xs :
  f(x)

无论 xs 是集合还是迭代器(甚至是生成器)都有效。 Java 不是这样工作的,这让我有点吃惊。

我正在实现一个库,我在其中将迭代器返回到一些内部集合而不是集合本身。但我现在担心这会迫使我的库的用户重新使用比 foreach 更旧/更丑陋的遍历方式。如果人们习惯于使用 foreach 结构,这是否有效地弃用了迭代器?

好吧,既然你想要一些现代的东西,那么使用 Java 8 你可以做到

Iterator<String> names = Arrays.asList("one","two","three").iterator();
for(String name : (Iterable<String>) () -> names) {
   System.out.println(name);
}

由于 for 循环需要一个可迭代对象,使用此技术,您可以使用 lambda 表达式从 Iterator 中提供 Iterable

不过,正如 fge 在另一个答案中提到的,这等同于以下 Java 8 使用方法引用并避免创建 Iterable 的表达式:

names.forEachRemaining(System.out::println);

因此,您可以将您的逻辑打包成一个 Consumer 并解决您的问题。

好吧,除了数组这种怪兽之外,您在此处使用的 "extended for" 循环只是 class 实现 Iterable 的结果。而这个接口只提供了一个方法to return an... Iterator.

这意味着如果你写代码:

for (final Foo foo: someInstanceImplementingIterableOfFoo) {
    doSomethingWith(foo);
}

它实际上等同于:

final Iterator<Foo> iterator = someInstanceImplementingIterableOfFoo.iterator();

Foo foo;

while (iterator.hasNext()) {
    foo = iterator.next();
    doSomethingWith(foo);
}

所以,答案真的是否定的,没有优雅的方式...

也就是说,除非你使用Java 8.它在Iterator上添加了forEachRemaining()

或者只是创建一个实用程序 class:

public final class IteratorWrap<T>
    implements Iterable<T>
{
    private final Iterator<T> iterator;

    public static <X> IteratorWrap<X> wrap(final Iterator<X> iterator)
    {
        return new IteratorWrap<>(iterator);
    }

    private IteratorWrap(final Iterator<T> iterator)
    {
        this.iterator = Objects.requireNonNull(iterator);
    }

    @Override
    public Iterator<T> iterator()
    {
        return iterator;
    }
}

在代码中,您只需:

for (final Foo foo: IteratorWrap.wrap(iteratorOfX))
    doSomethingWith(foo);
    Iterator<String> names = Arrays.asList("one", "two", "three").iterator();
    String foo;
    while((foo= Iterators.getNext(names, null))!=null){
        System.out.println(foo);
    }

Java的"enhanced"for循环要求被迭代的目标必须实现Iterable。但是如果你只有一个 Iterator,它没有实现 Iterable,那么就没有使用 Iterator 作为 [=28= 中的 foreach 循环目标的内置方法].

如果您不能使用 Java 8,您可以创建一个适配器 class 包装 Iterator、实现 Iterable 和 returns iterator() 方法中的包装迭代器。

class IterableIterator<T> implements Iterable<T>
{
   private Iterator<T> iterator;

   public IterableIterator(Iterator<T> iterator)
   {
      this.iterator = iterator;
   }

   @Override
   public Iterator<T> iterator()
   {
      return iterator;
   }
}

那么,如果你有一个Iterator,你可以这样使用它:

Iterator<MyClass> itr = getIteratorSomehow();
for (MyClass obj : new IterableIterator<MyClass>(itr))
{
    // ...
}