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で実装していた処理もこれらを使ってよりシンプルな形に置き換えられるかもしれません。