Perché è importante impostare il numero di contenitori e distribuire gli oggetti tra loro quanto più uniformemente possibile?
A HashSet
dovrebbe essere in grado di determinare l'appartenenza in O (1) tempo in media. Dalla documentation:
Questa classe offre prestazioni costante di tempo per le operazioni di base (aggiungere, rimuovere, contiene e dimensione), assumendo la funzione hash disperde gli elementi correttamente tra i secchi.
L'algoritmo un Hashset
utilizza per raggiungere questo obiettivo è quello di recuperare il codice hash per l'oggetto e usare questo per trovare il secchio giusto. Quindi itera su tutti gli elementi nel bucket fino a quando ne trova uno uguale. Se il numero di elementi nel bucket è maggiore di O (1), la ricerca richiederà più tempo di O (1).
Nel peggiore dei casi, se tutti gli elementi hanno un hash nello stesso bucket, occorrerà O (n) per determinare se un oggetto è nell'insieme.
Quale dovrebbe essere il rapporto ideale tra oggetto e benna?
C'è un compromesso spazio-tempo qui. Aumentando il numero di benne diminuisce la possibilità di collisioni. Tuttavia, aumenta anche i requisiti di memoria. Il set di hash ha due parametri initialCapacity
e loadFactor
che consentono di regolare il numero di bucket creati da HashSet
. Il fattore di caricamento predefinito è 0,75 e ciò va bene per la maggior parte degli scopi, ma se hai esigenze particolari puoi scegliere un altro valore.
Maggiori informazioni su questi parametri si possono trovare nella documentazione per HashMap
:
Questa implementazione fornisce prestazioni costanti in tempo per le operazioni di base (get e put), assumendo la funzione di hash disperde gli elementi correttamente tra i secchi. Le visualizzazioni di iterazione su collezione richiedono tempi proporzionali alla "capacità" dell'istanza di HashMap (il numero di bucket) più le sue dimensioni (il numero di mappature di valori-chiave). Pertanto, è molto importante non impostare la capacità iniziale troppo alta (o il fattore di carico troppo basso) se le prestazioni di iterazione sono importanti.
Un'istanza di HashMap ha due parametri che influiscono sulle sue prestazioni: capacità iniziale e fattore di carico. La capacità è il numero di bucket nella tabella hash e la capacità iniziale è semplicemente la capacità al momento della creazione della tabella hash. Il load factor è una misura di quanto è possibile ottenere la tabella hash prima che la sua capacità venga aumentata automaticamente.Quando il numero di voci nella tabella hash supera il prodotto del fattore di carico e la capacità corrente, la capacità viene approssimativamente raddoppiata chiamando il metodo rehash.
Come regola generale, il fattore di carico predefinito (.75) offre un buon compromesso tra costi di spazio e tempo. Valori più alti riducono l'overhead dello spazio ma aumentano il costo di ricerca (riflesso nella maggior parte delle operazioni della classe HashMap, inclusi get e put). Il numero previsto di voci nella mappa e il suo fattore di carico dovrebbero essere presi in considerazione quando si imposta la sua capacità iniziale, in modo da ridurre al minimo il numero di operazioni di rehash. Se la capacità iniziale è maggiore del numero massimo di voci diviso per il fattore di carico, non si verificherà mai alcuna operazione di restringimento.
Quindi è meglio avere 1 approccio per oggetto? – Jyotirup
Sì, ma HashSet lo fa per te, a condizione che il valore restituito da hashCode() sia distribuito correttamente. Se si restituisce una costante da hashCode(), ad esempio, tutti gli oggetti finiranno nello stesso bucket. –
@Jyotirup: Non è necessario raggiungere la situazione ideale di esattamente 1 oggetto per bucket. È normale che ci saranno alcune collisioni. –