Puedo ver que las respuestas propuestas se centran en el rendimiento. El artículo que se proporciona a continuación no proporciona nada nuevo con respecto al rendimiento, pero explica los mecanismos subyacentes. También tenga en cuenta que no se centra en los tres Collection
tipos mencionados en la pregunta, sino que aborda todos los tipos del System.Collections.Generic
espacio de nombres.
http://geekswithblogs.net/BlackRabbitCoder/archive/2011/06/16/c.net-fundamentals-choosing-the-right-collection-class.aspx
Extractos:
Diccionario <>
El Diccionario es probablemente la clase contenedora asociativa más utilizada. El Diccionario es la clase más rápida para búsquedas / inserciones / eliminaciones asociativas porque usa una tabla hash debajo de las cubiertas . Debido a que las claves tienen hash, el tipo de clave debe implementar correctamente GetHashCode () y Equals () de manera apropiada o debe proporcionar un IEqualityComparer externo al diccionario en construcción. El tiempo de inserción / eliminación / búsqueda de elementos en el diccionario se amortiza como tiempo constante - O (1) - lo que significa que no importa cuán grande sea el diccionario, el tiempo que se tarda en encontrar algo permanece relativamente constante. Esto es muy deseable para búsquedas de alta velocidad. El único inconveniente es que el diccionario, por la naturaleza del uso de una tabla hash, no está ordenado, por lo queno puede recorrer fácilmente los elementos de un diccionario en orden .
SortedDictionary <>
El SortedDictionary es similar al Diccionario en uso pero muy diferente en implementación. El SortedDictionary usa un árbol binario debajo de las cubiertas para mantener los elementos en orden por clave . Como consecuencia de la ordenación, el tipo utilizado para la clave debe implementar IComparable correctamente para que las claves se puedan ordenar correctamente. El diccionario ordenado intercambia un poco de tiempo de búsqueda por la capacidad de mantener los elementos en orden, por lo tanto, los tiempos de inserción / eliminación / búsqueda en un diccionario ordenado son logarítmicos - O (log n). Generalmente hablando, con tiempo logarítmico, puedes duplicar el tamaño de la colección y solo tiene que realizar una comparación extra para encontrar el artículo. Use el SortedDictionary cuando desee búsquedas rápidas pero también desee poder mantener la colección en orden por clave.
SortedList <>
SortedList es la otra clase de contenedor asociativo ordenada en los contenedores genéricos. Una vez más, SortedList, como SortedDictionary, usa una clave para ordenar los pares clave-valor . Sin embargo, a diferencia de SortedDictionary, los elementos de una SortedList se almacenan como una matriz ordenada de elementos. Esto significa que las inserciones y eliminaciones son lineales - O (n) - porque eliminar o agregar un elemento puede implicar mover todos los elementos hacia arriba o hacia abajo en la lista. Sin embargo, el tiempo de búsqueda es O (log n) porque SortedList puede usar una búsqueda binaria para encontrar cualquier elemento en la lista por su clave. Entonces, ¿por qué querrías hacer esto? Bueno, la respuesta es que si va a cargar SortedList por adelantado, las inserciones serán más lentas, pero debido a que la indexación de matrices es más rápida que los siguientes enlaces de objetos, las búsquedas son marginalmente más rápidas que un SortedDictionary. Una vez más, usaría esto en situaciones en las que desea búsquedas rápidas y desea mantener la colección en orden por clave, y donde las inserciones y eliminaciones son raras.
Resumen provisional de los procedimientos subyacentes
Los comentarios son bienvenidos, ya que estoy seguro de que no hice todo bien.
- Todas las matrices son de tamaño
n
.
- Matriz no ordenada = .Add / .Remove es O (1), pero .Item (i) es O (n).
- Array ordenado = .Add / .Remove es O (n), pero .Item (i) es O (log n).
Diccionario
Memoria
KeyArray(n) -> non-sorted array<pointer>
ItemArray(n) -> non-sorted array<pointer>
HashArray(n) -> sorted array<hashvalue>
Añadir
- Agregar
HashArray(n) = Key.GetHash
# O (1)
- Agregar
KeyArray(n) = PointerToKey
# O (1)
- Agregar
ItemArray(n) = PointerToItem
# O (1)
Eliminar
For i = 0 to n
, encuentra i
donde HashArray(i) = Key.GetHash
# O (log n) (matriz ordenada)
- Eliminar
HashArray(i)
# O (n) (matriz ordenada)
- Quitar
KeyArray(i)
# O (1)
- Quitar
ItemArray(i)
# O (1)
Obtiene el objeto
For i = 0 to n
, encuentra i
donde HashArray(i) = Key.GetHash
# O (log n) (matriz ordenada)
- Regreso
ItemArray(i)
Bucle a través
For i = 0 to n
, regreso ItemArray(i)
OrdenarDiccionario
Memoria
KeyArray(n) = non-sorted array<pointer>
ItemArray(n) = non-sorted array<pointer>
OrderArray(n) = sorted array<pointer>
Añadir
- Agregar
KeyArray(n) = PointerToKey
# O (1)
- Agregar
ItemArray(n) = PointerToItem
# O (1)
For i = 0 to n
, encuentra i
dónde KeyArray(i-1) < Key < KeyArray(i)
(usando ICompare
) # O (n)
- Agregar
OrderArray(i) = n
# O (n) (matriz ordenada)
Eliminar
For i = 0 to n
, encuentra i
donde KeyArray(i).GetHash = Key.GetHash
# O (n)
- Eliminar
KeyArray(SortArray(i))
# O (n)
- Eliminar
ItemArray(SortArray(i))
# O (n)
- Eliminar
OrderArray(i)
# O (n) (matriz ordenada)
Obtiene el objeto
For i = 0 to n
, encuentra i
donde KeyArray(i).GetHash = Key.GetHash
# O (n)
- Regreso
ItemArray(i)
Bucle a través
For i = 0 to n
, regreso ItemArray(OrderArray(i))
SortedList
Memoria
KeyArray(n) = sorted array<pointer>
ItemArray(n) = sorted array<pointer>
Añadir
For i = 0 to n
, encuentra i
dónde KeyArray(i-1) < Key < KeyArray(i)
(usando ICompare
) # O (log n)
- Agregar
KeyArray(i) = PointerToKey
# O (n)
- Agregar
ItemArray(i) = PointerToItem
# O (n)
Eliminar
For i = 0 to n
, encuentra i
donde KeyArray(i).GetHash = Key.GetHash
# O (log n)
- Eliminar
KeyArray(i)
# O (n)
- Eliminar
ItemArray(i)
# O (n)
Obtiene el objeto
For i = 0 to n
, encuentra i
donde KeyArray(i).GetHash = Key.GetHash
# O (log n)
- Regreso
ItemArray(i)
Bucle a través
For i = 0 to n
, regreso ItemArray(i)