ここでは非ジェネリックなコレクション型System.Collections.SortedListクラスについて解説します。 SortedListクラスを使用するよりも、SortedListに相当するジェネリックなコレクション型System.Collections.Generic.SortedList<T>クラスを使用することを強く推奨します。
SortedList
System.Collections.SortedListクラスは、HashtableクラスとArrayListクラスの両方の特徴を持ったコレクションです。 Hashtableと同じようにキーと値のペアで要素が格納され、キーによってコレクション内の要素にアクセスできるという点に加え、ArrayListのようにインデックスを指定して要素にアクセスすることができます。 また、SortedListという名前が示すとおり、要素が追加される時点でSortedListの内容はキーに基づいてソートされる点でHashtableと異なります。
基本的な操作
多くの操作はHashtableと同様ですが、SortedListを使った例によって基本的な操作について見ていきます。
using System;
using System.Collections;
class Sample {
static void Main()
{
SortedList list = new SortedList();
// キーを"foo"として値16を追加
list.Add("foo", 16);
list["bar"] = 72; // キー"bar"の値として値72を設定
Console.WriteLine("foo => {0}", list["foo"]); // キー"foo"の値を取得
Console.WriteLine("bar => {0}", list["bar"]); // キー"bar"の値を取得
Console.WriteLine("0 = {0}", list.GetByIndex(0)); // インデックス0の要素の値を取得
Console.WriteLine("1 = {0}", list.GetByIndex(1)); // インデックス1の要素の値を取得
// インデックス1の要素の値を取得
list.SetByIndex(1, "hoge");
Console.WriteLine("foo => {0}", list["foo"]); // キー"foo"の値を取得
Console.WriteLine("bar => {0}", list["bar"]); // キー"bar"の値を取得
// キー"foo", "bar"の要素が格納されているインデックスを取得
Console.WriteLine("IndexOfKey 'foo' => {0}", list.IndexOfKey("foo"));
Console.WriteLine("IndexOfKey 'bar' => {0}", list.IndexOfKey("bar"));
// 値16, 72の要素が格納されているインデックスを取得
Console.WriteLine("IndexOfValue 16 => {0}", list.IndexOfValue(16));
Console.WriteLine("IndexOfValue 72 => {0}", list.IndexOfValue(72));
}
}
Imports System
Imports System.Collections
Class Sample
Shared Sub Main()
Dim list As New SortedList()
' キーを"foo"として値16を追加
list.Add("foo", 16)
list("bar") = 72 ' キー"bar"の値として値72を設定
Console.WriteLine("foo => {0}", list("foo")) ' キー"foo"の値を取得
Console.WriteLine("bar => {0}", list("bar")) ' キー"bar"の値を取得
Console.WriteLine("0 = {0}", list.GetByIndex(0)) ' インデックス0の要素の値を取得
Console.WriteLine("1 = {0}", list.GetByIndex(1)) ' インデックス1の要素の値を取得
' インデックス1の要素の値を取得
list.SetByIndex(1, "hoge")
Console.WriteLine("foo => {0}", list("foo")) ' キー"foo"の値を取得
Console.WriteLine("bar => {0}", list("bar")) ' キー"bar"の値を取得
' キー"foo", "bar"の要素が格納されているインデックスを取得
Console.WriteLine("IndexOfKey 'foo' => {0}", list.IndexOfKey("foo"))
Console.WriteLine("IndexOfKey 'bar' => {0}", list.IndexOfKey("bar"))
' 値16, 72の要素が格納されているインデックスを取得
Console.WriteLine("IndexOfValue 16 => {0}", list.IndexOfValue(16))
Console.WriteLine("IndexOfValue 72 => {0}", list.IndexOfValue(72))
End Sub
End Class
foo => 16 bar => 72 0 = 72 1 = 16 foo => hoge bar => 72 IndexOfKey 'foo' => 1 IndexOfKey 'bar' => 0 IndexOfValue 16 => -1 IndexOfValue 72 => 0
例で示したとおり、キーによるアクセスの場合はHashtableと同様にインデクサを用いて行い、インデックスによるアクセスの場合はGetByIndexメソッドとSetByIndexメソッドを用いて行います。 インデクサにインデックスを指定しても、キーとしてしか扱われないので注意してください。
また、キーに該当する要素のインデックス、値に該当する要素のインデックスを取得するには、IndexOfKeyメソッドとIndexOfValueメソッドを使います。 該当するキーまたは値が見つからない場合は-1が返されます。
この例では使用していませんが、キーによる要素の削除にはRemoveメソッド、インデックスによる要素の削除にはRemoveAtメソッドを使用します。 Hashtableと同様、ContainsKeyメソッド、ContainsValueメソッドも用意されています。
列挙操作
SortedListの列挙もHashtableでの列挙と同様、DictionaryEntryに格納たキーと値のペアで列挙されますが、ソート済みの状態で列挙される点がHashtableとは異なります。 また、Hashtableと同様に、SortedListに格納されているすべてのキーはKeysプロパティ、値はValuesプロパティを通して参照できます。
using System;
using System.Collections;
class Sample {
static void Main()
{
SortedList list = new SortedList();
list["foo"] = 16;
list["bar"] = 72;
list["baz"] = 42;
// SortedListに格納されているキーと値のペアを列挙
Console.WriteLine("SortedList");
foreach (DictionaryEntry entry in list) {
Console.WriteLine("{0} => {1}", entry.Key, entry.Value);
}
// 同じ内容のHashtableを作成して列挙
Hashtable hash = new Hashtable(list);
Console.WriteLine("Hashtable");
foreach (DictionaryEntry entry in hash) {
Console.WriteLine("{0} => {1}", entry.Key, entry.Value);
}
// SortedListに格納されているすべてのキーを列挙
Console.WriteLine("[Keys]");
foreach (object key in list.Keys) {
Console.WriteLine(key);
}
// SortedListに格納されているすべての値を列挙
Console.WriteLine("[Values]");
foreach (object val in list.Values) {
Console.WriteLine(val);
}
}
}
Imports System
Imports System.Collections
Class Sample
Shared Sub Main()
Dim list As New SortedList()
list("foo") = 16
list("bar") = 72
list("baz") = 42
' SortedListに格納されているキーと値のペアを列挙
Console.WriteLine("SortedList")
For Each entry As DictionaryEntry In list
Console.WriteLine("{0} => {1}", entry.Key, entry.Value)
Next
' 同じ内容のHashtableを作成して列挙
Dim hash As New Hashtable(list)
Console.WriteLine("Hashtable")
For Each entry As DictionaryEntry In hash
Console.WriteLine("{0} => {1}", entry.Key, entry.Value)
Next
' SortedListに格納されているすべてのキーを列挙
Console.WriteLine("[Keys]")
For Each key As Object In list.Keys
Console.WriteLine(key)
Next
' SortedListに格納されているすべての値を列挙
Console.WriteLine("[Values]")
For Each val As Object In list.Values
Console.WriteLine(val)
Next
End Sub
End Class
SortedList bar => 72 baz => 42 foo => 16 Hashtable foo => 16 baz => 42 bar => 72 [Keys] bar baz foo [Values] 72 42 16
同じ内容のSortedListとHashtableを列挙していますが、SortedListの場合はキーによってソートされている点に注目してください。
ソート順のカスタマイズ
コンストラクタで適切なIComparerインターフェイスを指定することで、SortedListのキー比較時の動作をカスタマイズ出来ます。 HashtableではIEqualityComparerインターフェイスを用いてキーの同一性の比較のみを行いますが、SortedListではIComparerインターフェイスを使ってキーの同一性の比較と並べ替えを行います。 以下は、アルファベット順とは逆順(Z-Aの順)になるようにソートするIComparerを実装し、SortedListでの並べ替え順をカスタマイズする例です。
using System;
using System.Collections;
// アルファベット順とは逆順にソートするためのIComparer
class ReverseStringComparer : IComparer {
public int Compare(object x, object y)
{
// StringComparer.CurrentCulture.Compareとは逆の結果を返すようにする
return -1 * StringComparer.CurrentCulture.Compare(x, y);
}
}
class Sample {
static void Main()
{
SortedList orderdList = new SortedList(StringComparer.CurrentCulture);
orderdList["Alice"] = 1;
orderdList["Bob"] = 2;
orderdList["Charlie"] = 3;
orderdList["Dave"] = 4;
SortedList reverseOrderdList = new SortedList(new ReverseStringComparer());
reverseOrderdList["Alice"] = 1;
reverseOrderdList["Bob"] = 2;
reverseOrderdList["Charlie"] = 3;
reverseOrderdList["Dave"] = 4;
Console.WriteLine("orderdList");
foreach (DictionaryEntry entry in orderdList) {
Console.WriteLine("{0,-7} => {1}", entry.Key, entry.Value);
}
Console.WriteLine("reverseOrderdList");
foreach (DictionaryEntry entry in reverseOrderdList) {
Console.WriteLine("{0,-7} => {1}", entry.Key, entry.Value);
}
}
}
Imports System
Imports System.Collections
' アルファベット順とは逆順にソートするためのIComparer
Class ReverseStringComparer
Implements IComparer
Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
' StringComparer.CurrentCulture.Compareとは逆の結果を返すようにする
Return -1 * StringComparer.CurrentCulture.Compare(x, y)
End Function
End Class
Class Sample
Shared Sub Main()
Dim orderdList As New SortedList(StringComparer.CurrentCulture)
orderdList("Alice") = 1
orderdList("Bob") = 2
orderdList("Charlie") = 3
orderdList("Dave") = 4
Dim reverseOrderdList As New SortedList(New ReverseStringComparer())
reverseOrderdList("Alice") = 1
reverseOrderdList("Bob") = 2
reverseOrderdList("Charlie") = 3
reverseOrderdList("Dave") = 4
Console.WriteLine("orderdList")
For Each entry As DictionaryEntry In orderdList
Console.WriteLine("{0,-7} => {1}", entry.Key, entry.Value)
Next
Console.WriteLine("reverseOrderdList")
For Each entry As DictionaryEntry In reverseOrderdList
Console.WriteLine("{0,-7} => {1}", entry.Key, entry.Value)
Next
End Sub
End Class
orderdList Alice => 1 Bob => 2 Charlie => 3 Dave => 4 reverseOrderdList Dave => 4 Charlie => 3 Bob => 2 Alice => 1