web-dev-qa-db-ja.com

ScalaのSeqとIndexedSeq / LinearSeqの違いは何ですか?

Scalaコレクションのドキュメント には、この質問に対する手がかりがいくつかあります。

トレイトシーケンスには、LinearSeqとIndexedSeqの2つのサブトレイトがあります。これらは新しい操作を追加しませんが、それぞれが異なるパフォーマンス特性を提供します。線形シーケンスには効率的なヘッドおよびテール操作がありますが、インデックス付きシーケンスには効率的な適用、長さ、および(変更可能な場合)更新操作があります。

しかし、これはIndexedSeqの代わりにSeqをいつ使用するかについては説明していませんか? IndexedSeqまたはLinearSeqの実際の例が必要です。これらのコレクションは、Seqよりも優れています。

12
Milad Khajavi

Seqはスーパートレイトであるため、より一般的であり、線形とインデックス付きの両方のすべてのシーケンスに共通の特性を備えています。

Seqのコンパニオンオブジェクトの_Seq.apply_メソッドによってどのようなシーケンスが作成されるのか疑問に思っている場合は、実装。

Seq.applyを使用する場合は、Seqが必要であり、コードが線形であるかインデックス付きであるかを気にしないことを意味していることに注意してください

Tl; drの答えは次のとおりです。特定のパフォーマンス特性が必要な場合はLinearSeqまたはIndexedSeqを使用し、より一般的なSeq違いを気にしないとき

これはSeqのコンパニオンオブジェクトです。

_object Seq extends SeqFactory[Seq] {
  implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Seq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]

  def newBuilder[A]: Builder[A, Seq[A]] = immutable.Seq.newBuilder[A]
}
_

_newBuilder[A]_メソッドは、Seq.applyメソッド(トレイトGenericCompanionで定義)で確認できるように、Seqの構築に使用されるものです。

_def apply[A](elems: A*): CC[A] = {
   if (elems.isEmpty) empty[A]
   else {
     val b = newBuilder[A]
     b ++= elems
     b.result()
   }
 }
_

さて、問題は、_immutable.Seq.newBuilder[A]_は何を構築するのかということです。今回は_immutable.Seq_コンパニオンオブジェクトを見てみましょう。

_object Seq extends SeqFactory[Seq] {
// stuff
  def newBuilder[A]: Builder[A, Seq[A]] = new mutable.ListBuffer
}
_

可変のListBufferを構築します!何故ですか?これは、_mutable.ListBuffer_も_Builder[A, Seq[A]]_であるためです。これは、コレクションライブラリが新しいコレクションを構築するために使用するクラスです。

実際の出力コレクションは、次の行から取得されます(上記を参照)。

_b.result()
_

では、ListBuffer.result()の戻り値の型は何ですか? ListBufferで見てみましょう:

_// Implementation of abstract method in Builder
def result: List[A] = toList
_

ここに行きます:それはリストです。

Seq(1,2,3)は内部で_List[Int]_を返しますが、ここで重要なのは、Seq()を使用している場合は、どのような種類のコレクションがあるかを知る必要がないということです。より抽象的なインターフェースで十分であることを示唆しているからです

18

Seqは、IndexedSeqとLinearSeqの単なるスーパートレイトです。 Seqは、通常は一意で順序付けされていないSetとは対照的に、またキーと値のペアであるMapとは対照的に、順序付きリストです。
IndexedSeqとLinearSeqが登場しました。
IndexedSeqサブクラス、つまりVector、Range、Stringはすべて高速インデックスベースのアクセスであり、通常は高速更新です。これが可能なのは、内部的に配列(Stringなど)またはツリー(実際にはVectorで使用される32ファンアウトツリーなど)のようなこのようなデータ構造を使用しているためです。詳細については、 this )、または範囲。これは3つの数値です。開始、終了、ステップ..インデックスの計算は簡単です。
これとは対照的に、LinearSeqはすべてインデックスベースでアクセスが遅く、更新が遅いです。通常、それらはリンクリストのような構造を持っているためです。 Prependは、キュー、スタック、リストなど、すべての場合に高速ですが、内部リンクリスト構造のエッジに移動する必要があるため、追加が遅いことで有名です。ただし、独自の問題でトリックを使用するキューは除きます。トリックはここで説明されています ここ
広義には、IndexedSeqは、インデックスベースのアクセスと更新が高速なデータ構造であり、LinearSeqは、先頭に高速なデータ構造です。

9
Apurva Singh