Perché diverse raccolte Java hanno capacità predefinite diverse?


11

Guardando diversi costruttori di collezioni, viene in mente la domanda. Perché ArrayList () costruisce un elenco vuoto con una capacità iniziale di dieci e ArrayDeque () costruisce un deque array vuoto con una capacità iniziale sufficiente a contenere 16 elementi.


Non avevo nuovi che avevano un limite di capacità. Aggiungo semplicemente nuovi elementi con add (). Funziona sempre
Tulains Córdova,

1
Penso che stia parlando della dimensione iniziale dell'array all'interno dell'implementazione di ArrayList. Come suggerisce il nome, ArrayList è solo un vecchio array sotto le copertine e crea automaticamente array più grandi quando si tenta di aggiungere più elementi di quelli contenuti nell'attuale dimensione dell'array.
dsw88,

1
Penso che StringBuilder sia un altro con una capacità predefinita, era 10 o 16?
Ingo,

@Ingo Interessante. Non ero nemmeno a conoscenza di cose al di fuori delle collezioni incasinate di capacità ma suppongo che abbia senso. All'epoca non c'erano tag per la capacità, quindi non suscitavo molto interesse per altri usi.
Old Badman Gray,

Risposte:


17

Risposta breve

Perché la capacità di ArrayDeque deve essere una potenza di due e 16 è la potenza più piccola di due che è almeno 10.


ArrayDeque deve usare molte% operazioni dappertutto per avvolgere un array lineare che finge di essere circolare.

a % bpuò essere espresso come a & (b - 1) se b fosse un potere di due. L'AND bit a bit è enormemente più veloce, quindi la capacità di ArrayDeque è limitata a una potenza di due. Tutte le operazioni% vengono eseguite con il bitmasking invece dell'attuale% nell'implementazione.

Questo è anche il motivo per cui la più recente HashMap non utilizza le dimensioni della tabella dei numeri primi ma la potenza di due , ancora una volta perché l'operazione% deve essere eseguita così spesso e bit a bit ed è molto più veloce.

Quindi se la linea di base è 10, allora le strutture che hanno una potenza di due limitazioni dovrebbero usare 16 perché è la più piccola potenza di due che è almeno 10.


3

Non escludere la possibilità che non vi siano motivi specifici.

È possibile che queste due raccolte siano state scritte da diversi team. Entrambi hanno scelto un piccolo numero come capacità predefinita, ma la prima squadra ha pensato in modo decimale e ha scelto 10, mentre la seconda squadra ha pensato binario e ha scelto 16.


1

La risposta di Esailija è buona per questo caso specifico.

Più in generale, tuttavia, è un compromesso che dipende da molti fattori. Darò alcuni esempi:

  • Come viene generalmente utilizzata la struttura dei dati ? Le strutture di dati utilizzate come buffer di dati in genere preferiscono una capacità molto più elevata rispetto alle strutture di dati utilizzate per piccole tuple, ad esempio.
  • Quali dimensioni predefinite dei dati si inseriscono in una riga della cache sulla piattaforma CPU di destinazione? Può fare una grande differenza nelle prestazioni se il valore predefinito si adatta alla riga della cache. La scelta di 10 è come impostazione predefinita in Java potrebbe essere perché una matrice di 10 parole a 32 bit più l'overhead di matrice / oggetto si inserisce in una riga della cache di 64 byte.
  • Quanto apprezzi lo spazio rispetto all'efficienza di runtime ? Se si desidera migliorare le prestazioni di runtime, è generalmente preferibile pre-allocare più spazio per evitare ulteriori riassegnazioni in seguito.

Come risultato di questi compromessi, è abbastanza comprensibile che diverse implementazioni di raccolta possano avere una capacità predefinita ottimale diversa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.