SortedList<TKey,TValue>
と SortedDictionary<TKey,TValue>
の間に実際の実際的な違いはありますか?どちらか一方を使用し、他方を使用しない状況はありますか?
はい-それらのパフォーマンス特性は大きく異なります。それらをSortedList
およびSortedTree
と呼ぶ方が、実装をより密接に反映するため、おそらくより良いでしょう。
それぞれの状況( SortedList
、 SortedDictionary
)については、MSDNのドキュメントを参照してください。ここに素敵な要約があります(SortedDictionary
ドキュメントから):
SortedDictionary<TKey, TValue>
ジェネリッククラスは、O(log n)を取得するバイナリ検索ツリーです。ここで、nはディクショナリ内の要素の数です。この点では、SortedList<TKey, TValue>
ジェネリッククラスに似ています。 2つのクラスには類似したオブジェクトモデルがあり、両方ともO(log n)取得があります。 2つのクラスの違いは、メモリの使用と挿入および削除の速度です。
SortedList<TKey, TValue>
は、SortedDictionary<TKey, TValue>
よりも少ないメモリを使用します。
SortedDictionary<TKey, TValue>
は、SortedList<TKey, TValue>
のO(n)とは対照的に、ソートされていないデータ、O(log n)の挿入および削除操作が高速です。ソートされたデータからリストが一度に作成される場合、
SortedList<TKey, TValue>
はSortedDictionary<TKey, TValue>
よりも高速です。
(SortedList
は、ツリーを使用するのではなく、実際にソートされた配列を保持します。それでも、要素を見つけるためにバイナリ検索を使用します。)
これが役立つ場合は、表形式のビューです...
パフォーマンスの観点から:
+------------------+---------+----------+--------+----------+----------+---------+
| Collection | Indexed | Keyed | Value | Addition | Removal | Memory |
| | lookup | lookup | lookup | | | |
+------------------+---------+----------+--------+----------+----------+---------+
| SortedList | O(1) | O(log n) | O(n) | O(n)* | O(n) | Lesser |
| SortedDictionary | n/a | O(log n) | O(n) | O(log n) | O(log n) | Greater |
+------------------+---------+----------+--------+----------+----------+---------+
* Insertion is O(1) for data that are already in sort order, so that each
element is added to the end of the list (assuming no resize is required).
実装の観点から:
+------------+---------------+----------+------------+------------+------------------+
| Underlying | Lookup | Ordering | Contiguous | Data | Exposes Key & |
| structure | strategy | | storage | access | Value collection |
+------------+---------------+----------+------------+------------+------------------+
| 2 arrays | Binary search | Sorted | Yes | Key, Index | Yes |
| BST | Binary search | Sorted | No | Key | Yes |
+------------+---------------+----------+------------+------------+------------------+
生のパフォーマンスが必要な場合は、大まかに言い換えると、SortedDictionary
の方が適しています。より少ないメモリオーバーヘッドとインデックス取得が必要な場合は、SortedList
の方が適しています。 whichをいつ使用するかの詳細については、この質問を参照してください。
SortedList
について少し混乱しているように見えるので、Reflectorを開いてこれを確認しました。実際には、バイナリ検索ツリーではありませんキーと値のペアのソートされた(キーによる)配列です。キーと値のペアと同期してソートされ、バイナリ検索に使用されるTKey[] keys
変数もあります。
ここに、私の主張をバックアップするためのソース(.NET 4.5をターゲットとする)があります。
プライベートメンバー
// Fields
private const int _defaultCapacity = 4;
private int _size;
[NonSerialized]
private object _syncRoot;
private IComparer<TKey> comparer;
private static TKey[] emptyKeys;
private static TValue[] emptyValues;
private KeyList<TKey, TValue> keyList;
private TKey[] keys;
private const int MaxArrayLength = 0x7fefffff;
private ValueList<TKey, TValue> valueList;
private TValue[] values;
private int version;
SortedList.ctor(IDictionary、IComparer)
public SortedList(IDictionary<TKey, TValue> dictionary, IComparer<TKey> comparer) : this((dictionary != null) ? dictionary.Count : 0, comparer)
{
if (dictionary == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
}
dictionary.Keys.CopyTo(this.keys, 0);
dictionary.Values.CopyTo(this.values, 0);
Array.Sort<TKey, TValue>(this.keys, this.values, comparer);
this._size = dictionary.Count;
}
SortedList.Add(TKey、TValue):void
public void Add(TKey key, TValue value)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
int num = Array.BinarySearch<TKey>(this.keys, 0, this._size, key, this.comparer);
if (num >= 0)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}
this.Insert(~num, key, value);
}
SortedList.RemoveAt(int):void
public void RemoveAt(int index)
{
if ((index < 0) || (index >= this._size))
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
}
this._size--;
if (index < this._size)
{
Array.Copy(this.keys, index + 1, this.keys, index, this._size - index);
Array.Copy(this.values, index + 1, this.values, index, this._size - index);
}
this.keys[this._size] = default(TKey);
this.values[this._size] = default(TValue);
this.version++;
}
SortedListのMSDNページ をご覧ください。
備考セクションから:
SortedList<(Of <(TKey, TValue>)>)
ジェネリッククラスは、O(log n)
を取得するバイナリ検索ツリーです。n
は、ディクショナリ内の要素の数です。この点では、SortedDictionary<(Of <(TKey, TValue>)>)
ジェネリッククラスに似ています。 2つのクラスには類似したオブジェクトモデルがあり、両方ともO(log n)
を取得します。 2つのクラスの違いは、メモリの使用と挿入および削除の速度です。
SortedList<(Of <(TKey, TValue>)>)
は、SortedDictionary<(Of <(TKey, TValue>)>)
よりも少ないメモリを使用します。
SortedDictionary<(Of <(TKey, TValue>)>)
には、O(log n)
のO(n)
とは対照的に、SortedList<(Of <(TKey, TValue>)>)
に対して、ソートされていないデータの挿入および削除操作が高速化されています。ソートされたデータからリストが一度に作成される場合、
SortedList<(Of <(TKey, TValue>)>)
はSortedDictionary<(Of <(TKey, TValue>)>)
よりも高速です。
これは、パフォーマンスを相互に比較する方法を視覚的に表したものです。
このトピックについては既に十分に述べられていますが、簡単にするために、ここに私の見解を示します。
ソートされた辞書は次の場合に使用する必要があります-
反対側では、Sorted Listは次の場合に使用する必要があります-
お役に立てれば!!
インデックスアクセス(ここで説明)は実際的な違いです。後続または先行にアクセスする必要がある場合は、SortedListが必要です。 SortedDictionaryはそれを行うことができないため、並べ替えの使用方法(first/foreach)にはかなり制限があります。