Scalaコレクションのドキュメント には、この質問に対する手がかりがいくつかあります。
トレイトシーケンスには、LinearSeqとIndexedSeqの2つのサブトレイトがあります。これらは新しい操作を追加しませんが、それぞれが異なるパフォーマンス特性を提供します。線形シーケンスには効率的なヘッドおよびテール操作がありますが、インデックス付きシーケンスには効率的な適用、長さ、および(変更可能な場合)更新操作があります。
しかし、これはIndexedSeq
の代わりにSeq
をいつ使用するかについては説明していませんか? IndexedSeq
またはLinearSeq
の実際の例が必要です。これらのコレクションは、Seq
よりも優れています。
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()を使用している場合は、どのような種類のコレクションがあるかを知る必要がないということです。より抽象的なインターフェースで十分であることを示唆しているからです
Seqは、IndexedSeqとLinearSeqの単なるスーパートレイトです。 Seqは、通常は一意で順序付けされていないSetとは対照的に、またキーと値のペアであるMapとは対照的に、順序付きリストです。
IndexedSeqとLinearSeqが登場しました。
IndexedSeqサブクラス、つまりVector、Range、Stringはすべて高速インデックスベースのアクセスであり、通常は高速更新です。これが可能なのは、内部的に配列(Stringなど)またはツリー(実際にはVectorで使用される32ファンアウトツリーなど)のようなこのようなデータ構造を使用しているためです。詳細については、 this )、または範囲。これは3つの数値です。開始、終了、ステップ..インデックスの計算は簡単です。
これとは対照的に、LinearSeqはすべてインデックスベースでアクセスが遅く、更新が遅いです。通常、それらはリンクリストのような構造を持っているためです。 Prependは、キュー、スタック、リストなど、すべての場合に高速ですが、内部リンクリスト構造のエッジに移動する必要があるため、追加が遅いことで有名です。ただし、独自の問題でトリックを使用するキューは除きます。トリックはここで説明されています ここ 。
広義には、IndexedSeqは、インデックスベースのアクセスと更新が高速なデータ構造であり、LinearSeqは、先頭に高速なデータ構造です。