1. 序章

Scalaには、scala.collectionパッケージの下にある非常に豊富なコレクションライブラリがあります。

このチュートリアルでは、一般的なScalaコレクションの概要とその使用方法について簡単に説明します。

2. Scalaコレクションの種類

Scalaには2種類のコレクションがあります–可変と不変です。 いくつかの違いを指摘しましょう。

2.1. 可変コレクション

可変コレクションは、その場で更新または拡張されます。 これは、副作用としてコレクションの要素を追加、変更、または削除できることを意味します。これらのコレクションには、コレクションを変更する操作があります。 すべての可変コレクションクラスは、scala.collection.mutableパッケージに含まれています。

2.2. 不変のコレクション

すべての不変のコレクションはscala.collection.immutableの下にあります。 追加、削除、更新などの操作を実行できますが、これらの操作は常に新しいコレクションを返し、古いコレクションは変更されません。

3. Scalaコレクション階層の概要

Scalaのコレクションクラスは、TraversableおよびIterableの特性で始まります。 これらの特性は、リストセット、マップの3つの主要なカテゴリに分かれています。

Traversableトレイトを使用すると、コレクション全体をトラバースできます。これは、他のすべてのコレクションの基本トレイトです。 foreachメソッドに関する一般的な動作を実装します。

Iterable トレイトは、階層の最上位から次のトレイトであり、反復可能なコレクションの基本トレイトです。 コレクションの要素を一度に1つずつループできるイテレーターを定義します。イテレーターを使用する場合、コレクションをトラバースできるのは1回だけです。 これは主に、各要素が反復プロセス中に処理されるためです。

それでは、Scalaライブラリの最も一般的な不変のコレクションのいくつかを調べてみましょう。

4. 最も一般的に使用されるScalaコレクション

4.1. リスト

Scalaリストは、内部的に不変のリンクリストを表します。 要素の順序を維持し、重複を含めることもできます。 このクラスは後入れ先出し(LIFO)のスタックのようなアクセスパターンに最適です。

また、テールリストの構造共有も実装しています。 これは、多くの操作でメモリフットプリントが一定であるか、メモリフットプリントがまったくないことを意味します。

リストには、 O(1)の先頭とヘッド/テールアクセスがあります。 ただし、他のほとんどの操作は O(n)です。 これには、長さ、追加、逆方向、および要素のインデックスベースのルックアップが含まれます。

たとえば、整数のリストを宣言できます。

val numbersList: List[Int] = List(1, 2, 3 ,4)
val emptyList: List[Int] = List() // Empty List

このListクラスには、抽象メンバーisEmpty、head、tailを実装するscala.Nilとscala。::の2つの実装ケースクラスが付属しています。要素を含むScalaリストは、xを使用して表すことができます。 :: xs 、ここで x は先頭で、xsは残りのリストです。 Nil は、空のリストを表します。

val numbersList: List[Int] = 1 :: 2 :: 3 :: 4 :: Nil  // List of Integers
val emptyList: List[Int] = Nil  // Empty List
val x :: xs = numbersList
assert(x == 1) // true
assert(xs == List(2, 3, 4)) // true

上記の例では、 x ::xs表記を使用してnumbersListを表すことができます。 xxsの値を出力すると、 x がリストの先頭になり、xsが残りのリストになります。 。

リストには3つの基本的な操作があります。

いいえ。 方法 説明
1 リストの最初の要素を返します
2 しっぽ head(最初の要素)を除くすべての要素で構成されるListを返します
3 isEmpty リストが空の場合、trueを返します

それぞれを順番に使用してみましょう。

val numbersList: List[Int] = 1 :: 2 :: 3 :: 4 :: Nil
assert(numbersList.head == 1) // true
assert(numbersList.tail == List(2, 3, 4)) // true
assert(numbersList.isEmpty) // false

その他の一般的な操作には、2つのリストの連結、統一リストの作成、およびリストの反転が含まれます。

List(1,2) ::: List(3,4) // List(1, 2, 3, 4)

List.fill(3)(100) // List(100, 100, 100)

List(1,2,3,4).reverse // List(4, 3, 2, 1)

Scala List メソッドの完全なリストは、ScalaDocにあります。

4.2. セット

Scala Set は、ユニークな要素のコレクションです。 デフォルトでは、Scalaは不変のセットを使用します。要素を格納するための順序は維持されません。

不変セットを次のように宣言できます。

val emptySet: Set[Int] = Set() // Empty set
val numbersSet: Set[Int] = Set(1, 2, 3, 4) // Set of integers

可変のSetを使用する場合は、collection.mutableから明示的にインポートする必要があります。

val mutableSet = collection.mutable.Set(1, 2, 3)

Set の操作は、Listの操作と似ています。

いいえ。 方法 説明
1 Setの最初の要素を返します
2 しっぽ head(最初の要素)を除くすべての要素で構成されるSetを返します
3 isEmpty Set が空の場合、trueを返します

だから、それらを試してみましょう:

Set(1, 2, 3, 4).head // 1
Set(1, 2, 3, 4).tail // Set(2, 3, 4)
Set(1, 2, 3, 4).isEmpty // false

Scala Set のメソッドの完全なリストは、ScalaDocにあります。

4.3. マップ

Map は、キーと値のペアのコレクションであり、キーは常に一意です。 Scalaは、その可変バージョンと不変バージョンを提供します。 デフォルトでは、マップの不変バージョンがインポートされます:

val immutableMap = Map(1 -> "a", 2 -> "b")
val mutableMap = collection.mutable.Map(1 -> "a", 2 -> "b")

マップを操作する方法は少し異なります。

いいえ。 方法 説明
1 キー Mapのすべてのキーを含むイテラブルを返します
2 Mapのすべての値を含むイテラブルを返します
3 isEmpty Map が空の場合、trueを返します

これらのメソッドがどのように機能するかを見てみましょう。

Map(1 -> "a", 2 -> "b").keys // res0: Iterable[Int] = Set(1, 2)

Map(1 -> "a", 2 -> "b").values // res1: Iterable[String] = Iterable(a, b)

Map(1 -> "a", 2 -> "b").isEmpty // false

getメソッドはオプションの値を返します。 Mapトレイトでのそのシグネチャは次のとおりです。

def get(key: K): Option[V]

キーが存在する場合は、 Some コンテキストで値を返しますが、キーが存在しない場合は、Noneを返します。

Map(1 -> "a", 2 -> "b").get(1) // Some(a)

Map(1 -> "a", 2 -> "b").get(3) // None

Scala Map のメソッドの完全なリストは、ScalaDocにあります。

4.4. タプル

Tuple は、同じコンテナーにさまざまなアイテムを格納する方法を提供するコレクションです。 固定数のアイテムを組み合わせます。これを全体として渡すことができ、クラスを個別に宣言する必要はありません。

Scala 2.xには、 Tuple2 Tuple3…最大Tuple22という名前のクラスがあります。

括弧内にいくつかの要素を配置すると、Tupleが得られます。 intStringのタプルは次のようになります。

val t1 = (1, "A")

宣言t1は、タプルの単なる構文糖衣です。

val t1 = Tuple2(1, "A")

タプルの要素にアクセスする方法は2つあります。 最初の方法は、要素番号でそれらにアクセスすることです。

val tuple3 = (1, "One", "A") // tuple3: (Int, String, String)
tuple3._1 // 1
tuple3._2 // One
tuple3._3 // A

要素にアクセスする2番目の方法は、Scalaの古典的なパターンマッチングを使用することです。このようにして、Tuple要素をいくつかの適切な変数名に割り当てることができます。

val (num, word, char)  = (1, "One", 'A')
num // 1
word // One
char // A

productIterator メソッドを使用して、Tupleを反復処理できます。

val tuple = (1,2,3,4)
tuple.productIterator.foreach(println)

この場合、次のように出力されます。

1
2
3
4

技術的には、Scala 2.xタプルはコレクションクラスではないため、Iterable特性を拡張しません。

5. 結論

このチュートリアルでは、Scalaのコレクションライブラリについて説明しました。 可変コレクションと不変コレクションの違いを調べ、Scalaで一般的に使用されるコレクションを調べました。

完全なコードは、GitHubから入手できます。