En algún código de biblioteca, tengo una lista que puede contener 50,000 elementos o más..NET: ¿Cómo verificar eficientemente la exclusividad en una lista <string> de 50,000 artículos?
Las personas que llaman a la biblioteca pueden invocar métodos que den como resultado la adición de cadenas a la lista. ¿Cómo controlo de manera eficiente la exclusividad de las cadenas que se agregan?
Actualmente, justo antes de agregar una cadena, escaneo toda la lista y comparo cada cadena con la cadena que se va a agregar. Esto comienza a mostrar problemas de escala por encima de 10.000 elementos.
Analizaré esto, pero estoy interesado en la información.
- si reemplazo la Lista <> con un diccionario <>, se ContainsKey() ser apreciablemente más rápido que la lista crece hasta 10.000 artículos y más allá?
- si difiero la verificación de exclusividad hasta que todos los artículos se hayan agregado, ¿será más rápido? En ese punto, necesitaría verificar cada elemento contra cualquier otro elemento, aún una operación n ^^ 2.
EDITAR
Algunos resultados básicos de referencia. Creé una clase abstracta que expone 2 métodos: Rellenar y Escanear. Fill simplemente llena la colección con n elementos (utilicé 50,000). El escaneo escanea la lista m veces (utilicé 5000) para ver si un valor dado está presente. Luego construí una implementación de esa clase para List y otra para HashSet.
Las cadenas utilizadas tienen uniformemente 11 caracteres de longitud y se generan aleatoriamente mediante un método en la clase abstracta.
Una micro-referencia muy básica.
Hello from Cheeso.Tests.ListTester
filling 50000 items...
scanning 5000 items...
Time to fill: 00:00:00.4428266
Time to scan: 00:00:13.0291180
Hello from Cheeso.Tests.HashSetTester
filling 50000 items...
scanning 5000 items...
Time to fill: 00:00:00.3797751
Time to scan: 00:00:00.4364431
Así, para las cadenas de esa longitud, HashSet es aproximadamente 25 veces más rápido que la lista, al escanear la singularidad. Además, para este tamaño de colección, HashSet tiene cero penalización sobre la Lista al agregar elementos a la colección.
Los resultados son interesantes y no son válidos. Para obtener resultados válidos, necesitaría hacer intervalos de calentamiento, pruebas múltiples, con selección aleatoria de la implementación. Pero estoy seguro de que eso moverá el listón solo ligeramente.
Gracias a todos.
Edit2
Después de la adición de la aleatorización y multple ensayos, HashSet constantemente supera a la lista, en este caso, en alrededor de 20 veces.
Estos resultados no son necesariamente válidos para cadenas de longitud variable, objetos más complejos o diferentes tamaños de colección.
Un diccionario definitivamente será más rápido, ya que utiliza un hash debajo de las cubiertas. – Joe
Un 'HashSet' será aún más rápido, ya que no usa espacio adicional para un valor. – SLaks
si difiere el cheque, puede ordenar la lista (o una copia) y verificar cada elemento con el vecino. no necesitarías cada elemento contra cada otro elemento entonces. –