Answers:
简而言之,迭代器保持状态,可遍历不保持状态。
A Traversable有一个抽象方法:foreach。当您调用时foreach,集合将依次保存传递给函数的所有元素。
另一方面,具有Iterablehas作为抽象方法iterator,它返回Iterator。你可以叫next上Iterator你的选择的时间去下一个元素。在执行此操作之前,它必须跟踪它在集合中的位置以及下一步。
Iterableextends Traversable,所以我想你的意思Traversable是不是Iterable。
Traversable接口不需要保持状态,而遵守Iterator接口则需要保持状态。
TraversableS中的Iterable不保留任何迭代状态。这是Iterator创建并返回Iterable,保持状态。
可以将其视为吹和吸之间的区别。
调用Traversables foreach或其派生方法后,它将一次将其值吹入函数中-因此它可以控制迭代。
通过Iteratorif返回Iterable,您可以从中吸取值,控制何时自己移至下一个。
TL;博士 Iterables是Traversables可以产生状态Iterators
首先,要知道Iterable是的子特性Traversable。
第二,
Traversable需要实现该foreach方法,该方法将被其他所有方法使用。
Iterable需要实现该iterator方法,该方法将被其他所有方法使用。
例如,findfor Traversable用途的实现foreach(通过for理解)并BreakControl在找到令人满意的元素后抛出异常以暂停迭代。
trait TravserableLike {
def find(p: A => Boolean): Option[A] = {
var result: Option[A] = None
breakable {
for (x <- this)
if (p(x)) { result = Some(x); break }
}
result
}
}
相比之下,Iterable减重写此实施和电话find上Iterator,一旦元素被发现,它只是停止迭代:
trait Iterable {
override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
iterator.find(p)
}
trait Iterator {
def find(p: A => Boolean): Option[A] = {
var res: Option[A] = None
while (res.isEmpty && hasNext) {
val e = next()
if (p(e)) res = Some(e)
}
res
}
}
最好不要在Traversable迭代中抛出异常,但这是使用just进行部分迭代的唯一方法foreach。
从一个角度看,Iterable它是更苛刻/更强大的特性,因为您可以轻松实现foreachusing iterator,但不能真正实现iteratorusing foreach。
总之,Iterable提供了一种通过有状态的暂停,继续或停止迭代的方法Iterator。使用Traversable,它全有还是全无(流量控制没有例外)。
在大多数情况下,这并不重要,您将需要更通用的界面。但是,如果您需要对迭代进行更多的自定义控制,则需要一个Iterator,您可以从中进行检索Iterable。
丹尼尔的回答听起来不错。让我看看是否可以用我自己的话说。
因此,Iterable可以为您提供一个迭代器,使您可以一次遍历元素(使用next()),并根据需要停止并继续。为此,迭代器需要为元素的位置保留一个内部“指针”。但是Traversable为您提供了一次遍历所有元素而无需停止的方法foreach。
像Range(1,10)这样的东西只需要2个整数作为Traversable状态即可。但是Range(1,10)作为Iterable可以为您提供一个迭代器,该迭代器需要使用3个整数作为状态,其中一个是索引。
考虑到Traversable还提供foldLeft,foldRight,因此它的foreach需要以已知的固定顺序遍历元素。因此,可以为Traversable实现一个迭代器。例如def iterator = toList.iterator
Traversable了(它一直保留为2.14之前已弃用的别名)Iterable