Iterable 接口是不是有关于多次使用的官方合同?
Posted
技术标签:
【中文标题】Iterable 接口是不是有关于多次使用的官方合同?【英文标题】:Is there any official contract for the Iterable interface with respect to multiple usage?Iterable 接口是否有关于多次使用的官方合同? 【发布时间】:2013-03-24 18:54:37 【问题描述】:从 Java 5 开始,我们有了新的 java.lang.Iterable
类型,可以在 foreach 循环中使用:
for (Object element : iterable);
Iterable
合约没有指定在处理 Iterable 之前是否可以多次调用其iterator()
方法。即,尚不清楚以下内容是否适用于所有Iterables
:
for (Object element : iterable);
for (Object element : iterable);
例如,Iterator
包装实现不能使用两次:
public class OneShotIterable<T> implements Iterable<T>
private final Iterator<T> it;
public OneShotIterable(Iterator<T> it)
this.it = it;
@Override
public Iterator<T> iterator()
return it;
对于大多数 Iterables
而言,这无关紧要,因为它们实际上是经过改造的 Collection API 类型,例如 List
、Set
,它们已经为它们的 iterator()
方法定义了明确的合约。
我的问题是:我的OneShotIterable
实施是否违反了我忽略的某些合同?换句话说,Iterable
的用户会期望它是可重用的吗?如果是这样,Java 5 专家组是否有“官方”建议如何处理这种“一次性”Iterables
(例如在第二次调用时抛出IllegalStateException
)?
【问题讨论】:
难道你不能在每次调用 iterator() 时增加 OneShotIterable 的一个字段,如果它是 gte n 则抛出异常? @LukasEder doh 你把它编辑掉了 【参考方案1】:我可以在标准库中找到的一个先例是 DirectoryStream
接口。
它的 Javadoc 包含以下段落(强调他们的):
虽然
DirectoryStream
扩展了Iterable
,但它不是通用的Iterable
,因为它只支持单个Iterator
;调用iterator
方法来获取第二个或后续迭代器会抛出IllegalStateException
。
对我来说,这意味着两件事:
Iterable
上的隐含合同是您应该能够多次迭代(甚至可能同时进行!)
文档中的粗体警告加上 IllegalStateException
可能是处理您自己的类/接口中不合规的最佳方法。
【讨论】:
【参考方案2】:并不是我的问题的真正答案,但 Apache Commons Collections 已在其 IteratorUtils
类中解决了此问题:
IteratorUtils.asIterable(Iterator)
IteratorUtils.asMultipleUseIterable(Iterator)
两者都是IteratorIterable
类型的工厂方法。上述区别清楚地表明,在将Iterators
包装在Iterables
中时必须小心。
【讨论】:
以上是关于Iterable 接口是不是有关于多次使用的官方合同?的主要内容,如果未能解决你的问题,请参考以下文章
请问java中的Iterator和Iterable有些啥区别啊?