Existe-t-il une réelle différence pratique entre un SortedList<TKey,TValue>
et un SortedDictionary<TKey,TValue>
? Y a-t-il des circonstances dans lesquelles vous utiliseriez spécifiquement l'un et pas l'autre?
Oui, leurs caractéristiques de performance diffèrent considérablement. Il serait probablement préférable de les appeler SortedList
et SortedTree
, car cela reflète plus précisément la mise en œuvre.
Examinez les documents MSDN pour chacune d’elles ( SortedList
, SortedDictionary
) pour obtenir des détails sur les performances de différentes opérations dans différentes situations. Voici un bon résumé (de la SortedDictionary
docs):
Le
SortedDictionary<TKey, TValue>
La classe générique est un arbre de recherche binaire avec une extraction O (log n), où n est le nombre d'éléments du dictionnaire. En cela, il est similaire auSortedList<TKey, TValue>
classe générique. Les deux classes ont des modèles d'objet similaires et les deux ont une extraction O (log n). La différence entre les deux classes est l'utilisation de la mémoire et la vitesse d'insertion et de suppression:
SortedList<TKey, TValue>
utilise moins de mémoire queSortedDictionary<TKey, TValue>
.
SortedDictionary<TKey, TValue>
a des opérations d’insertion et de suppression plus rapides pour les données non triées, O (log n) par opposition à O(n) pourSortedList<TKey, TValue>
.Si la liste est remplie en une fois à partir de données triées,
SortedList<TKey, TValue>
est plus rapide queSortedDictionary<TKey, TValue>
.
(SortedList
maintient en fait un tableau trié, plutôt que d'utiliser un arbre. Il utilise toujours la recherche binaire pour trouver des éléments.)
Voici une vue tabulaire si cela peut aider ...
Dans une perspective performance :
+------------------+---------+----------+--------+----------+----------+---------+
| 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).
Dans une perspective d'implémentation :
+------------+---------------+----------+------------+------------+------------------+
| 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 |
+------------+---------------+----------+------------+------------+------------------+
Pour approximativement paraphraser, si vous avez besoin de performances brutes, SortedDictionary
pourrait être un meilleur choix. Si vous avez besoin d'une surcharge de mémoire et d'une récupération indexée, SortedList
convient mieux. Voir cette question pour en savoir plus sur quand utiliser lequel.
J'ai craqué d'ouvrir Reflector pour jeter un coup d'œil à ceci car il semble y avoir un peu de confusion à propos de SortedList
. Ce n'est en fait pas un arbre de recherche binaire, c'est un tableau trié (par clé) de paires clé-valeur. Il y a aussi TKey[] keys
variable qui est triée de manière synchrone avec les paires clé-valeur et utilisée pour la recherche binaire.
Voici quelques sources (ciblant .NET 4.5) pour sauvegarder mes revendications.
membres privés
// 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++;
}
Découvrez la page MSDN pour SortedList :
De la section Remarques:
La classe générique
SortedList<(Of <(TKey, TValue>)>)
est un arbre de recherche binaire avec la récupérationO(log n)
, oùn
est le nombre d'éléments dans le dictionnaire. En cela, il est similaire à la classe génériqueSortedDictionary<(Of <(TKey, TValue>)>)
. Les deux classes ont des modèles d'objet similaires et les deux ont la récupérationO(log n)
. La différence entre les deux classes est l'utilisation de la mémoire et la vitesse d'insertion et de suppression:
SortedList<(Of <(TKey, TValue>)>)
utilise moins de mémoire queSortedDictionary<(Of <(TKey, TValue>)>)
.
SortedDictionary<(Of <(TKey, TValue>)>)
a des opérations d'insertion et de suppression plus rapides pour les données non triées,O(log n)
par opposition àO(n)
pourSortedList<(Of <(TKey, TValue>)>)
.Si la liste est remplie en une fois à partir de données triées,
SortedList<(Of <(TKey, TValue>)>)
est plus rapide queSortedDictionary<(Of <(TKey, TValue>)>)
.
Ceci est une représentation visuelle de la façon dont les performances se comparent les unes aux autres.
On en dit déjà assez sur le sujet, mais pour rester simple, voici mon point de vue.
Dictionnaire trié devrait être utilisé quand-
De l'autre côté, Liste triée devrait être utilisé lorsque-
J'espère que cela t'aides!!
L'accès à l'index (mentionné ici) est la différence pratique. Si vous devez accéder au successeur ou au prédécesseur, vous avez besoin de SortedList. SortedDictionary ne peut pas faire cela, donc vous êtes assez limité avec la façon dont vous pouvez utiliser le tri (first/foreach).