Collectionとは?
C#
のCollection
(コレクション)とは、複数の要素を管理、操作するためのデータ構造の総称です。
データの集まりを効率的に操作するための方法を提供して、要素の追加や削除などの操作をサポートします。
今回は、HashSet
,Stack
,Queue
について紹介します。
HashSet
HashSet
はList
と似たコレクションです。
違う点は、要素の重複を許容しない点です。
追加しようとした要素が既に含まれている場合、自動的に無視されます。
大量の要素を重複しないようにList
に追加したいと思った場合、HashSet
を使えば簡単に実現できます。
HashSet
を使用するには、
using System.Collections.Generic;
が必要です。
追加
HashSet<int> hashSet = new HashSet<int>();
hashSet.Add(1);
hashSet.Add(2);
// 1は既に追加されるので無視される
hashSet.Add(1);
Queue
Queue
とは、待ち行列という意味です。
こちらもListと似ていますが、最初に追加されたものが最初に取り出されるという性質があります。
以下の特徴があります
- 先入れ先出し(
FIFO
) - 動的にサイズが変わるため、後からデータを追加できる
- シンプルなメソッドによる操作
行列の出来るラーメン店の前に
最初に来たお客さんから順に列に並び、先頭から順々に店内に入っていく、
そんなイメージです。
初期化
以下の場合、int
型のQueue
を作成します。
Queue
を使用するには、
using System.Collections.Generic;
が必要です。
Queue<int> queue = new Queue<int>();
追加
Queue
に追加する場合は、Add
ではなく、Enqueue
を使用します。
queue.Enqueue(1);
queue.Enqueue(2);
取り出し
Queue
から取り出す場合は、Remove
などではなく、Dequeue
を使用します。
Queue
は、FIFO(First In First Out)
なので、以下のコードでv1
に入るのは、
一番最初にEnqueue
で追加した値になります。
Queue
が空の場合は例外が発生します。
// 追加
queue.Enqueue(1);
queue.Enqueue(2);
// 取り出し
int v1 = queue.Dequeue();
TryDequeue
例外を発生させたくない場合は、TryDequeue
が使用できます。
if (queue.TryDequeue(out int value))
{
// Queueが空では無く、先頭の値を取り出せた
}
Peek
Queue
から取り出さずに、先頭の要素を取得します。
Queue
が空の場合は例外が発生します。
int v1 = queue.Peek();
TryPeek
例外を発生させたくない場合は、TryPeek
が使用できます。
if (queue.TryPeek(out int value))
{
// キューが空で無ければ、先頭の要素を取得
}
Clear
Queue
を全て削除する場合は、Clear
を使用します。
queue.Clear();
Stack
Stack
とは、積み重ねる、といった意味になります。
こちらもList
と似ていますが、Queue
とは逆で、
最後に追加されたものが最初に取り出されるという性質があります。
- 後入れ先出し(
LIFO
) - 動的にサイズが変わるため、後からデータを追加できる
- シンプルなメソッドによる操作
積み上げた本を崩さないように取り出すため、最後に積んだ本から取り上げる、
そんなイメージです。
初期化
以下の場合、int
型のStack
を作成します。
Stack
を使用するには、
using System.Collections.Generic;
が必要です。
Stack<int> stack = new Stack<int>();
追加
Add
ではなく、Push
で追加します。
stack.Push(1);
stack.Push(2);
取り出し
Remove
ではなく、Pop
で取り出します。
Stack
が空の場合は、例外が発生します。
LIFO(Last In First Out)
なので、以下のコードでvalueに入るのは、
直前にPush
した値になります。
stack.Push(1);
stack.Push(2);
int value = stak.Pop();
TryPop
例外を発生させたくない場合は、TryPop
が使用できます。
if (stack.TryPop(out int value))
{
// stackが空で無く、値を取り出せた
}
Peek
最後に追加した値を
Stack
から取り出さずに、最後の要素を取得します。
Stack
が空の場合は例外が発生します。
int value = stack.Peek();
TryPeek
例外を発生させたくない場合は、TryPeek
が使用できます。
if (stack.TryPeek(out int value))
{
// stackが空で無く、値を取得
}
Clear
Stack
を全て削除する場合は、Clear
を使用します。
stack.Clear();
それぞれの主な用途
HashSet
,Queue
,Stack
とも、がんばればList
で代用できますが、
それぞれの特性にあった使い方をすればよりシンプルに実装できるようになります。
HashSet
要素が重複しないため、追加する前に既に要素が存在するか気にしたり、
全て追加した後に重複する要素を削除したりする手間が無くなります。
Queue
ターン制のRPGのようなゲームで、敵味方の行動順を管理するのに使えます。
敵のAIやアニメーションなど、順に実行するようなケースでも使えそうです。
Stack
最後に追加したものが最初に取り出されるため、よくあるUndo
の操作にもStack
が使われています。
Unity
でもシーン遷移する際に今のシーン名をStack
に積んでおけば、
Stack
から直前のシーン名を取り出せるようになるため、
前にシーンへ順々に戻すような処理が実現できます。
まとめ
HashSet
,Queue
,Stack
という三つのCollection
について解説しました。
いずれもList
と似ていますが、用途に応じてうまく使い分けてください。
これまでList
で実装していた処理もこれらを使ってよりシンプルな形に置き換えられるかもしれません。