Łuk*_*nik 172 java iterator iterable
为什么Iterator界面没有扩展Iterable?
该iterator()方法可以简单地返回this.
它是故意还是只是对Java设计师的监督?
能够使用像这样的迭代器的for-each循环会很方便:
for(Object o : someContainer.listSomeObjects()) {
....
}
Run Code Online (Sandbox Code Playgroud)
where listSomeObjects()返回一个迭代器.
Jon*_*eet 212
迭代器是有状态的.这个想法是,如果你调用Iterable.iterator()两次,你将得到独立的迭代器 - 无论如何,对于大多数的迭代.在你的场景中显然不是这种情况.
例如,我通常可以写:
public void iterateOver(Iterable<String> strings)
{
for (String x : strings)
{
System.out.println(x);
}
for (String x : strings)
{
System.out.println(x);
}
}
Run Code Online (Sandbox Code Playgroud)
这应该打印两次集合 - 但是使用你的方案,第二个循环总是会立即终止.
Pau*_*ams 65
因为迭代器通常指向集合中的单个实例.Iterable意味着可以从对象获取迭代器来遍历其元素 - 并且不需要迭代单个实例,这是迭代器所代表的.
Bar*_*ney 59
对于我的0.02美元,我完全同意Iterator不应该实现Iterable,但我认为增强的for循环应该接受.我认为整个"使迭代器可迭代"的论点出现在解决语言缺陷的过程中.
引入增强的for循环的全部原因是它"在迭代集合和数组时消除了迭代器和索引变量的苦差事和错误倾向"[ 1 ].
Collection<Item> items...
for (Iterator<Item> iter = items.iterator(); iter.hasNext(); ) {
Item item = iter.next();
...
}
for (Item item : items) {
...
}
Run Code Online (Sandbox Code Playgroud)
那为什么同样的论点不适用于迭代器呢?
Iterator<Iter> iter...
..
while (iter.hasNext()) {
Item item = iter.next();
...
}
for (Item item : iter) {
...
}
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,都删除了对hasNext()和next()的调用,并且没有对内部循环中的迭代器的引用.是的,我理解Iterables可以被重用来创建多个迭代器,但是这一切都发生在for循环之外:在循环内部,迭代器返回的项目一次只有一个前进项目.
此外,允许这样也可以很容易地使用for循环for Enumerations,正如其他地方所指出的那样,它类似于Iterators而不是Iterables.
所以不要让Iterator实现Iterable,而是更新for循环以接受.
干杯,
McD*_*ell 17
正如其他人所指出的,Iterator并且Iterable是两个不同的东西.
此外,Iterator实现早于增强循环.
使用静态方法导入时使用简单的适配器方法来克服此限制也是微不足道的:
for (String line : in(lines)) {
System.out.println(line);
}
Run Code Online (Sandbox Code Playgroud)
示例实施:
/**
* Adapts an {@link Iterator} to an {@link Iterable} for use in enhanced for
* loops. If {@link Iterable#iterator()} is invoked more than once, an
* {@link IllegalStateException} is thrown.
*/
public static <T> Iterable<T> in(final Iterator<T> iterator) {
assert iterator != null;
class SingleUseIterable implements Iterable<T> {
private boolean used = false;
@Override
public Iterator<T> iterator() {
if (used) {
throw new IllegalStateException("SingleUseIterable already invoked");
}
used = true;
return iterator;
}
}
return new SingleUseIterable();
}
Run Code Online (Sandbox Code Playgroud)
在Java 8适应的Iterator一种Iterable变简单了:
for (String s : (Iterable<String>) () -> iterator) {
Run Code Online (Sandbox Code Playgroud)
正如其他人所说,可以多次调用Iterable,每次调用返回一个新的Iterator; 迭代器只使用一次.所以他们是相关的,但服务于不同的目的.然而,令人沮丧的是,"compact for"方法仅适用于迭代.
我将在下面描述的是一种充分利用两个世界的方法 - 即使基础数据序列是一次性的,也可以返回Iterable(用于更好的语法).
诀窍是返回实际触发工作的Iterable的匿名实现.因此,不是执行生成一次性序列然后返回Iterator的工作,而是返回一个Iterable,每次访问它都会重做工作.这可能看起来很浪费,但通常你只会调用Iterable一次,即使你多次调用它,它仍然有合理的语义(不像一个简单的包装器使得Iterator"看起来像是一个Iterable,这赢了"如果使用两次则失败).
例如,假设我有一个DAO,它提供了一系列来自数据库的对象,我希望通过迭代器提供对它的访问(例如,如果不需要,则避免在内存中创建所有对象).现在我可以返回一个迭代器,但这会使循环中返回的值变得难看.所以我把所有内容都包装在一个anon Iterable中:
class MetricDao {
...
/**
* @return All known metrics.
*/
public final Iterable<Metric> loadAll() {
return new Iterable<Metric>() {
@Override
public Iterator<Metric> iterator() {
return sessionFactory.getCurrentSession()
.createQuery("from Metric as metric")
.iterate();
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以在这样的代码中使用它:
class DaoUser {
private MetricDao dao;
for (Metric existing : dao.loadAll()) {
// do stuff here...
}
}
Run Code Online (Sandbox Code Playgroud)
这让我可以使用紧凑的for循环,同时仍然保持增量内存使用.
这种方法是"懒惰的" - 当请求Iterable时,工作没有完成,但只有在内容被迭代后才能完成 - 你需要知道它的后果.在带有DAO的示例中,这意味着在数据库事务中迭代结果.
所以有各种各样的警告,但在许多情况下,这仍然是一个有用的习惯用语.
令人难以置信的是,还没有人给出这个答案.以下是Iterator使用新的Java 8 Iterator.forEachRemaining()方法"轻松"迭代的方法:
Iterator<String> it = ...
it.forEachRemaining(System.out::println);
Run Code Online (Sandbox Code Playgroud)
当然,有一个"更简单"的解决方案可以直接使用foreach循环,包含Iterator在Iterablelambda中:
for (String s : (Iterable<String>) () -> it)
System.out.println(s);
Run Code Online (Sandbox Code Playgroud)
Iterator是一个允许您迭代某些东西的界面.它是通过某种集合进行移动的实现.
Iterable 是一个功能接口,表示某些东西包含一个可访问的迭代器.
在Java8中,这让生活变得非常简单......如果你有一个Iterator但需要一个,Iterable你可以简单地做:
Iterator<T> someIterator;
Iterable<T> = ()->someIterator;
Run Code Online (Sandbox Code Playgroud)
这也适用于for循环:
for (T item : ()->someIterator){
//doSomething with item
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
45692 次 |
| 最近记录: |