可変コレクションおよび不変コレクション | 目次 |
最新版は Scala Documentation に移行しました。
Scala
のコレクションは、体系的に可変および不変コレクションを区別している。
可変 (mutable) コレクションは上書きしたり拡張することができる。これは副作用としてコレクションの要素を変更、追加、または削除することができることを意味する。
一方、不変 (immutable) コレクションは変わることが無い。追加、削除、または更新を模倣した演算は提供されるが、全ての場合において演算は新しいコレクションを返し、古いコレクションは変わることがない。
コレクションクラスの全ては scala.collection パッケージもしくは mutable、immutable、generic のどれかのサブパッケージに定義されている。 クライアントコードに必要なコレクションのクラスのほどんどには可変性に関して異なる特性を持つ 3つの形態が定義されおり、ぞれぞれ scala.collection、scala.collection.immutable、か scala.collection.mutable のパッケージに存在する。
scala.collection.immutable パッケージのコレクションは、誰にとっても不変であることが保証されている。そのようなコレクションは作成後には一切変更されることがない。したがって、異なる時点で何回同じコレクションの値にアクセスしても常に同じ要素を持つコレクションが得られることに依存できる。
scala.collection.mutable パッケージのコレクションは、コレクションを上書き変更する演算がある。 だから可変コレクションを扱うということは、どのコードが、何時どのコレクションを変更したのかということを理解する必要があることを意味する。
scala.collection パッケージのコレクションは、可変か不変かのどちらでもありうる。例えば、collection.IndexedSeq[T] は、collection.immutable.IndexedSeq[T] とcollection.mutable.IndexedSeq[T] 両方の親クラスだ。一般的に、scala.collection パッケージの基底コレクションは不変コレクションと同じインターフェイスを定義し、scala.collection.mutable パッケージ内の可変コレクションは、副作用を伴う変更演算を不変インターフェイスに加える。
基底コレクションと不変コレクションの違いは、不変なコレクションのクライアントは、他の誰もコレクションを変更しないという保証があるのに対し、基底コレクションのクライアントは自分ではコレクションを変更しなかったという約束しかできない。たとえ静的な型がコレクションを変更するような演算を提供していなくても、実行時の型は他のクライアントが手を加えることができる可変コレクションである可能性がある。
デフォルトでは Scala は常に不変コレクションを選ぶ。たとえば、scala パッケージのデフォルトのバインディングにより、なんの接頭辞や import もなくただ Set と書くと不変な集合 (set) が返ってき、Iterable と書くと不変で反復可能 (iterable) なコレクションが返ってくる。可変なデフォルト実装を取得するには、collection.mutable.Set または collection.mutable.Iterable と明示的に記述する必要がある。
可変と不変の両方のバージョンのコレクションを使用する場合に便利な慣例は collection.mutable パッケージだけをインポートすることだ。
import scala.collection.mutable |
これにより、接頭辞なしの Set は不変なコレクションを参照するのに対し、mutable.Set は可変のものを参照する。
コレクション階層内の最後のパッケージが collection.generic だ。このパッケージには、コレクションを実装するための基本的なパーツが含まれている。 コレクションクラスがいくつかの演算を generic内のクラスに委譲することはよくあるが、 フレームワークのユーザーが generic内のクラスが必要になることは普通はありえない。
利便性と後方互換性のために、いつくかの重要な型は scala パッケージ内に別名を定義してあるため、インポート無しで単純な名前でコレクションを使うことができる。List型が良い例で、以下の名前でもアクセスすることができる
scala.collection.immutable.List 定義元 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
scala.List scalaパッケージのエイリアス経由 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
List scala._ は常に自動的にインポートされるため |
エイリアスされているその他の型は次のとおり: Traversable, Iterable, Seq, IndexedSeq, Iterator, Stream, Vector, StringBuilder, Range。
次の図は scala.collection パッケージ内の全てのコレクションを示す。これらはすべて、高レベルの抽象クラスやトレイトで一般に可変と不変の両方の実装を持っている。
次の図は scala.collection.immutable パッケージ内の全てのコレクションを示す。
そして、次の図は scala.collection.mutable パッケージ内の全てのコレクションを示す。
(以上三つ全ての図は decodified.com の Matthias によって生成された。)
続いては、コレクションAPIの概要
可変コレクションおよび不変コレクション | 目次 |