.net - example - hashset como funciona c#
¿Cuál es la diferencia entre HashSet<T> y List<T>? (8)
¿Puede explicar cuál es la diferencia entre HashSet<T>
y List<T>
en .NET?
Quizás puedas explicar con un ejemplo en qué casos HashSet<T>
debería preferirse a List<T>
?
Gracias.
A diferencia de una Lista <> ...
Un HashSet es una Lista sin miembros duplicados.
Debido a que un HashSet está limitado a contener solo entradas únicas, la estructura interna está optimizada para la búsqueda (en comparación con una lista): es considerablemente más rápido
Agregar a un HashSet devuelve un valor booleano - falso si la adición falla debido a que ya existe en Conjunto.) Puede realizar operaciones de conjunto matemático contra un Conjunto: Unión / Intersección / IsSubsetOf, etc.
HashSet no implementa IList solo ICollection
No puede usar índices con un HashSet, solo enumeradores.
La razón principal para usar un HashSet sería si está interesado en realizar operaciones de Conjunto.
Dado 2 conjuntos: hashSet1 y hashSet2
//returns a list of distinct items in both sets
HashSet set3 = set1.Union( set2 );
vuela en comparación con una operación equivalente usando LINQ. ¡También es mejor escribir!
La lista es una lista ordenada. Es
- accedido por un índice entero
- puede contener duplicados
- tiene un orden predecible
HashSet es un conjunto. Eso:
- Puede bloquear elementos duplicados (ver Add(T) )
- No garantiza el orden de los elementos dentro del conjunto
- Tiene las operaciones que esperaría en un conjunto, por ejemplo , IntersectWith, IsProperSubsetOf, UnionWith.
La lista es más adecuada cuando desea acceder a su colección como si fuera una matriz a la que pudiera agregar, insertar y eliminar elementos. HashSet es una mejor opción si desea tratar su colección como una "bolsa" de artículos en los que el orden no es importante o cuando desea compararlos con otros conjuntos que utilizan operaciones como IntersectWith o UnionWith.
La lista no es necesariamente única, mientras que hashset es, para uno.
Para ser más precisos, demostrémoslo con ejemplos,
No puede usar HashSet como en el siguiente ejemplo.
HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
for (int i = 0; i < hashSet1.Count; i++)
Console.WriteLine(hashSet1[i]);
hashSet1[i]
produciría un error:
No se puede aplicar la indexación con [] a una expresión del tipo ''System.Collections.Generic.HashSet''
Puedes usar la declaración foreach:
foreach (var item in hashSet1)
Console.WriteLine(item);
No puede agregar elementos duplicados a HashSet mientras List le permite hacer esto y mientras agrega un elemento a HashSet, puede verificar si contiene el elemento o no.
HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
if (hashSet1.Add("1"))
Console.WriteLine("''1'' is successfully added to hashSet1!");
else
Console.WriteLine("''1'' could not be added to hashSet1, because it contains ''1''");
HashSet tiene algunas funciones útiles como IntersectWith
, UnionWith
, IsProperSubsetOf
, ExceptWith
, SymmetricExceptWith
, etc.
IsProperSubsetOf
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
HashSet<string> hashSet3 = new HashSet<string>() { "1", "2", "3", "4", "5" };
if (hashSet1.IsProperSubsetOf(hashSet3))
Console.WriteLine("hashSet3 contains all elements of hashSet1.");
if (!hashSet1.IsProperSubsetOf(hashSet2))
Console.WriteLine("hashSet2 does not contains all elements of hashSet1.");
UnionWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
hashSet1.UnionWith(hashSet2); //hashSet1 -> 3, 2, 4, 6, 8
IntersectWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" }
hashSet1.IntersectWith(hashSet2);//hashSet1 -> 4, 8
ExceptWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
hashSet1.ExceptWith(hashSet2);//hashSet1 -> 5, 6
SymmetricExceptWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
hashSet1.SymmetricExceptWith(hashSet2);//hashSet1 -> 4, 5, 6
Por cierto, el orden no se conserva en HashSets. En el ejemplo, agregamos el elemento "2" al final, pero está en el segundo orden:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
hashSet1.Add("1"); // 3, 4, 8, 1
hashSet1.Remove("4"); // 3, 8, 1
hashSet1.Add("2"); // 3, 2 ,8, 1
Si decide aplicar estas estructuras de datos al uso real en el desarrollo basado en datos, un HashSet es MUY útil para probar la replicación contra fuentes de adaptadores de datos, para la limpieza y migración de datos.
Además, si se utiliza la clase de anotaciones de datos, se puede implementar la lógica de claves en las propiedades de clase y controlar efectivamente un índice natural (agrupado o no) con un HashSet, donde esto sería muy difícil en una implementación de lista.
Una buena opción para usar una lista es implementar genéricos para múltiples medios en un Modelo de visualización, como enviar una lista de clases a una MVC View para un DropDownList Helper, y también para enviar como una construcción JSON a través de WebApi. La lista permite una lógica de recopilación de clases típica y mantiene la flexibilidad para un enfoque más similar a la "Interfaz" para computar un modelo de vista única para diferentes medios.
Un HashSet<T>
es una clase diseñada para darle O(1)
búsqueda de contención (es decir, esta colección contiene un objeto particular, y dígame la respuesta rápidamente).
Una List<T>
es una clase diseñada para proporcionarle una colección con O(1)
acceso aleatorio que puede crecer dinámicamente (pensar matriz dinámica). Puede probar la contención en el tiempo O(n)
(a menos que la lista esté ordenada, entonces puede hacer una búsqueda binaria en el tiempo O(log n)
).
Tal vez puedas explicar con un ejemplo en qué casos
HashSet<T>
debería preferirse aList<T>
Cuando desee probar la contención en O(1)
.
Una lista es una colección ordenada de objetos de tipo T que, a diferencia de una matriz, puede agregar y eliminar entradas.
Debería utilizar una lista en la que desee hacer referencia a los miembros en el orden en que los almacenó y accederá a ellos por una posición en lugar de por el artículo mismo.
Un HashSet es como un diccionario en el que el elemento en sí es la clave, así como el valor, el orden no está garantizado.
Utilizaría un HashSet en el que quiera verificar que un objeto se encuentre en la colección
Use una List<T>
cuando desee:
- Almacene una colección de artículos en un orden determinado.
Si conoce el índice del artículo que desea (en lugar del valor del artículo en sí), la recuperación es O(1)
. Si no conoce el índice, encontrar el artículo lleva más tiempo, O(n)
para una colección no ordenada.
Use un Hashset<T>
cuando desee:
- Descubra rápidamente si un determinado objeto está contenido en una colección.
Si conoce el nombre de la cosa que desea buscar, Lookup es O(1)
(esa es la parte ''Hash''). No mantiene un orden como lo hace la List<T>
y no puede almacenar duplicados (agregar un duplicado no tiene ningún efecto, esa es la parte ''Establecer'').
Un ejemplo de cuándo usar un Hashset<T>
sería si desea saber si una palabra que se reproduce en un juego de Scrabble es una palabra válida en inglés (u otro idioma). Sería aún mejor si quisieras construir un servicio web para ser utilizado por todas las instancias de una versión en línea de dicho juego.
Una List<T>
sería una buena estructura de datos para crear el marcador para rastrear los puntajes de los jugadores.