Scala:Scala集合中的Traversable和Iterable特性有什么区别?

Rah*_*hul 95 scala scala-collections

我已经看过这个问题,但仍然不理解Iterable和Traversable特征之间的区别.谁能解释一下?

Dun*_*gor 221

把它想象成吹和吸吮之间的区别.

当你调用一个Traversables foreach或它的派生方法时,它会一次一个地将它的值放入你的函数中 - 所以它可以控制迭代.

通过a Iterator返回Iterable,你可以从中取出值,控制何时自己移动到下一个值.

  • 人们用来调用_pushing_和_pulling_而不是_blowing_和_sucking_,但我喜欢你的开放态度. (47认同)
  • 棒极了. (36认同)
  • 在下次面试中被问到时,永远不要忘记这一点 (2认同)

Dan*_*ral 118

简而言之,迭代器保持状态,遍历不会.

A Traversable有一个抽象方法:foreach.当你调用时foreach,集合将一个接一个地传递它保存的所有元素.

另一方面,有一个Iterable抽象方法iterator,它返回一个Iterator.您可以在选择时调用nexta Iterator来获取下一个元素.在你做之前,它必须跟踪它在集合中的位置,以及接下来的内容.

  • `Traversable```Iterable`不会保持任何迭代状态.它是由"Iterable"创建并返回的"Iterator",用于保持状态. (10认同)
  • 但是"Iterable"扩展了`Traversable`,所以我猜你的意思是`Traversable`s不是'Iterable`s. (4认同)
  • @RobinGreen我的意思是遵守`Traversable`接口不需要保持状态,同时遵守`Iterator`接口. (4认同)
  • 值得注意的是,从 2.13 开始, Traversable 特性已被弃用。引用 Stefan Zeiger 的话说,“Traversable 抽象在当前的库中还没有发挥其作用,并且很可能不会在新设计中重新出现。我们想做的一切都可以用 Iterable 来表达。” (3认同)

Pau*_*per 21

tl; dr IterablesTraversables可以产生有状态的Iterators


首先,要知道这Iterable是次要的Traversable.

第二,

  • Traversable需要实现其他所有foreach方法使用的方法.

  • Iterable需要实现其他所有iterator方法使用的方法.

例如,findfor的Traversable使用实现foreach(通过for comprehension)并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
  }
}
Run Code Online (Sandbox Code Playgroud)

相比之下,Iterable减覆盖这个实现,并呼吁findIterator,一旦元素被发现,它只是停止迭代:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

不要为Traversable迭代抛出异常会很好,但这是使用just时部分迭代的唯一方法foreach.

从一个角度来看,Iterable是更苛刻/更强大的特性,因为你可以轻松实现foreach使用iterator,但你无法真正实现iterator使用foreach.


总之,Iterable提供了一种通过有状态暂停,恢复或停止迭代的方法Iterator.随着Traversable,它是全部或全部(没有流量控制的例外).

大多数时候它并不重要,你会想要更通用的界面.但是如果你需要更多的自定义控制迭代,你需要一个Iterator,你可以从一个Iterable.