In alcuni codici di libreria, ho una lista che può contenere 50.000 elementi o più..NET: come verificare in modo efficiente l'unicità in un elenco <string> di 50.000 elementi?
I chiamanti della libreria possono richiamare i metodi che determinano l'aggiunta di stringhe all'elenco. Come faccio a verificare in modo efficiente l'univocità delle stringhe aggiunte?
Attualmente, appena prima di aggiungere una stringa, analizzo l'intero elenco e confronta ogni stringa con la stringa da aggiungere. Questo inizia a mostrare problemi di scala superiori a 10.000 elementi.
Farò un punto di riferimento, ma mi interessa l'intuizione.
- se sostituire l'elenco <> con un dizionario <>, sarà ContainsKey() essere sensibilmente più veloce come la lista cresce fino a 10.000 articoli e oltre?
- se differisco il controllo di unicità fino a quando non sono stati aggiunti tutti gli elementi, sarà più veloce? A quel punto avrei bisogno di controllare ogni elemento contro ogni altro elemento, ancora un n ^^ 2 operazione.
EDIT
Alcuni risultati di base di riferimento. Ho creato una classe astratta che espone 2 metodi: Fill and Scan. Riempi semplicemente la raccolta con n elementi (ne ho usati 50.000). Scansione esegue la scansione della lista m volte (ho usato 5000) per vedere se è presente un determinato valore. Quindi ho creato un'implementazione di quella classe per List e un'altra per HashSet.
Le stringhe utilizzate erano lunghe uniformemente 11 caratteri e generate casualmente tramite un metodo nella classe astratta.
Un micro-benchmark di base.
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
Così, per le stringhe di quella lunghezza, HashSet è circa 25x più veloce di lista, durante la scansione di unicità. Inoltre, per questa dimensione di raccolta, HashSet ha zero penalità su Elenco quando si aggiungono elementi alla raccolta.
I risultati sono interessanti e non validi. Per ottenere risultati validi, avrei bisogno di fare intervalli di riscaldamento, prove multiple, con selezione casuale dell'implementazione. Ma sono fiducioso che ciò sposterebbe la barra solo leggermente.
Grazie a tutti.
EDIT2
Dopo aver aggiunto la randomizzazione e multple prove, HashSet supera costantemente lista in questo caso, di circa 20x.
Questi risultati non sono necessariamente validi per stringhe di lunghezza variabile, oggetti più complessi o dimensioni di raccolta diverse.
Un dizionario sarà sicuramente più veloce, in quanto utilizza un hash sotto le coperte. – Joe
Un 'HashSet' sarà ancora più veloce, in quanto non utilizza spazio aggiuntivo per un valore. – SLaks
se si rinvia il controllo, è possibile ordinare l'elenco (o una copia) e controllare ciascun elemento rispetto al suo vicino. allora non avresti bisogno di ogni elemento contro ogni altro elemento. –