web-dev-qa-db-ja.com

Scala:ScalaコレクションでのTraversable特性とIterable特性の違いは何ですか?

この質問 を見ましたが、それでもIterableとTraversableの特性の違いを理解していません。誰か説明できますか?

91
Rahul

簡単に言えば、イテレータは状態を保持しますが、トラバーサルは保持しません。

Traversableには、foreachという抽象メソッドが1つあります。 foreachを呼び出すと、コレクションは、渡された関数に保持しているすべての要素を次々に送ります。

一方、Iterableには、iteratorを返す抽象メソッドIteratorがあります。 nextIteratorを呼び出して、選択したときに次の要素を取得できます。それまでは、コレクション内のどこにあるのか、次に何をするのかを追跡する必要があります。

113

吹くと吸うの違いと考えてください。

Traversables foreach、またはその派生メソッドを呼び出すと、値を一度に1つずつ関数に吹き込むため、反復を制御できます。

ただし、Iteratorによって返されるIterableを使用すると、値を削除して、次の値にいつ移動するかを自分で制御できます。

217
Duncan McGregor

tl; drIterablesは、ステートフルTraversablesを生成できるIteratorsである


まず、IterableTraversableのサブトレイトであることを知ってください。

第二に、

  • Traversableには、他のすべてで使用されるforeachメソッドの実装が必要です。

  • Iterableには、他のすべてで使用されるiteratorメソッドの実装が必要です。

たとえば、findTraversableの実装では、foreachを使用して(理解のために)、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減算はこの実装をオーバーライドし、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
  }
}

Traversableの反復に対して例外をスローしないのはいいことですが、それがforeachだけを使用する場合に部分的に反復する唯一の方法です。

Iterableを使用して簡単にforeachを実装できますが、実際にiteratorを実装することはできないため、1つの観点から、iteratorはより要求の厳しい強力な特性です。 foreachを使用します。


要約すると、Iterableは、ステートフルIteratorを介して反復を一時停止、再開、または停止する方法を提供します。 Traversableを使用すると、すべてまたは何もありません(フロー制御の例外はありません)。

ほとんどの場合、それは重要ではなく、より一般的なインターフェイスが必要になります。しかし、繰り返しをさらにカスタマイズして制御する必要がある場合は、Iteratorから取得できるIterableが必要になります。

20
Paul Draper

ダニエルの答えはいいですね。自分の言葉で表現できるかどうか見てみましょう。

したがって、Iterableはイテレータを提供できます。イテレータを使用すると、要素を一度に1つずつトラバースし(next()を使用)、必要に応じて停止して実行できます。そのためには、イテレータは要素の位置への内部「ポインタ」を保持する必要があります。ただし、Traversableは、停止することなくすべての要素を一度にトラバースするメソッドforeachを提供します。

Range(1、10)のようなものは、Traversableとして状態として2つの整数のみを持つ必要があります。しかし、IterableとしてのRange(1、10)は、状態に3つの整数を使用する必要があるイテレータを提供します。その1つはインデックスです。

TraversableはfoldLeft、foldRightも提供することを考慮すると、foreachは既知の固定された順序で要素をトラバースする必要があります。したがって、Traversableのイテレータを実装することが可能です。例えば。 def iterator = toList.iterator

0
user11595225