有没有办法在 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))
{
// ...
}
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))
{
// ...
}