首页 文章

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

提问于
浏览
89

我看了this question但仍然不理解Iterable和Traversable特征之间的区别 . 谁能解释一下?

3 回答

  • 19

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

    Traversable 有一个抽象方法: foreach . 当你调用 foreach 时,该集合将为它传递的所有元素提供一个接一个的传递函数 .

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

  • 108

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

    当您调用 Traversable s foreach 或其派生方法时,它会一次将其值放入您的函数中 - 因此它可以控制迭代 .

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

  • 209

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


    首先,要知道 IterableTraversable 的子索引 .

    第二,

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

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

    例如,对于 Traversable find 的实现使用 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
      }
    }
    

    相比之下, Iterable subtract会覆盖此实现,并在 Iterator 上调用 find ,一旦找到该元素,它就会停止迭代:

    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 迭代抛出异常会很好,但这是仅使用 foreach 时部分迭代的唯一方法 .

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


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

    大多数情况下,它不需要更通用的界面 . 但是如果你需要更多的自定义控制迭代,你需要 Iterator ,你可以从 Iterable 检索 .

相关问题