Ciao! La conferenza di oggi
ArrayList
sarà, da un lato, più semplice e, dall'altro, più difficile delle precedenti. È più difficile, perché oggi guarderemo "sotto il cofano" ArrayList
e studieremo cosa gli succede durante le operazioni. D'altra parte, in questa lezione non ci sarà quasi alcun codice, per lo più immagini e spiegazioni. Quindi andiamo :) Come già sai, all'interno ArrayList
di 'a c'è un normale array, che funge da archivio dati. Nella maggior parte dei casi, non specifichiamo la dimensione esatta dell'elenco. Ma l'array interno deve avere una certa dimensione! Questo è vero. La sua dimensione predefinita è [10] .
public static void main(String[] args) {
ArrayList<Car> cars = new ArrayList<>();
}
Innanzitutto, diamo un'occhiata a come appare l'aggiunta di un nuovo elemento. Innanzitutto viene controllato se c'è abbastanza spazio nell'array interno e se può entrare un altro elemento. Se c'è spazio, il nuovo elemento viene aggiunto alla fine dell'elenco. Quando diciamo “fino alla fine” non intendiamo l’ultima cella dell’array (sarebbe strano). Questo si riferisce alla cella accanto all'ultimo elemento corrente. Il suo indice sarà pari a cars.size()
. La nostra lista è attualmente vuota ( cars.size() = 0
). Di conseguenza, un nuovo elemento verrà aggiunto alla cella con indice 0
.
ArrayList<Car> cars = new ArrayList<>();
Car ferrari = new Car("Ferrari 360 Spider");
cars.add(ferrari);
Qui è tutto chiaro. Cosa accadrà se l'inserimento viene effettuato al centro, cioè tra più elementi?
public static void main(String[] args) {
ArrayList<Car> cars = new ArrayList<>();
Car ferrari = new Car("Ferrari 360 Spider");
Car bugatti = new Car("Bugatti Veyron");
Car lambo = new Car("Lamborghini Diablo");
Car ford = new Car("Ford Modneo");
cars.add(ferrari);
cars.add(bugatti);
cars.add(lambo);
cars.add(1, ford);//добавляем ford в ячейку 1, которая уже занята
}
Ancora una volta, controlla prima se c'è abbastanza spazio nell'array. Se c'è abbastanza spazio gli elementi vengono spostati a destra partendo dalla cella dove inseriamo il nuovo elemento. Incolliamo nella cella con indice 1. Cioè, l'elemento dalla cella 3 viene copiato nella cella 4, l'elemento 2 nella cella 3, l'elemento 1 nella cella 2. Successivamente, il nostro nuovo elemento viene incollato al suo posto. L'elemento precedente ( bugatti
) è già stato copiato da lì in una nuova posizione. Ora vediamo come avverrebbe questo processo se non ci fosse spazio per l'inserimento nell'array. Naturalmente prima viene controllato se c'è abbastanza spazio. Se si scopre che non c'è abbastanza spazio, ArrayList
all'interno di 'a viene creato un nuovo array di dimensioni (dimensione di OldArray * 1,5) + 1. Nel nostro caso, il nuovo array avrà una dimensione di 16 celle. Tutti gli elementi correnti verranno copiati lì immediatamente. Il vecchio array verrà eliminato dal Garbage Collector e rimarrà solo quello nuovo ed espanso. Ora c'è spazio libero per il nuovo elemento. Lo incolliamo nella cella 3, che è occupata. Ora inizia la procedura familiare. Tutti gli elementi che iniziano con l'indice 3 vengono spostati di una cella a destra e un nuovo elemento viene aggiunto silenziosamente. E ora l'inserimento è avvenuto con successo! Abbiamo risolto l'inserimento. Ora parliamo della rimozione degli elementi . Come ricorderete, quando lavoravamo con gli array, abbiamo riscontrato un problema: quando li abbiamo cancellati, sono rimasti dei "buchi". L'unica soluzione era spostare gli elementi a sinistra ogni volta che venivano eliminati e dovevi scrivere tu stesso il codice per lo spostamento. ArrayList
funziona secondo lo stesso principio, ma in esso questo meccanismo è già implementato automaticamente. Ecco come appare: E alla fine otteniamo il risultato desiderato: L'elemento lambo
è stato eliminato con successo. Qui abbiamo effettuato una rimozione dal centro. È chiaro che l'eliminazione dalla fine della lista risulterà più rapida, poiché verrà eliminato l'elemento desiderato senza spostare tutti gli altri. Diamo un'altra occhiata alla dimensione dell'array interno e alla sua memorizzazione in memoria. L'espansione dell'array è un processo che richiede una certa quantità di risorse. Pertanto, non dovresti creare ArrayList
con la dimensione predefinita se sai per certo che avrà almeno 100 elementi. Quando arrivi a inserire il centesimo elemento, l'array interno si espanderà 6 volte , trasferendo ogni volta tutti gli elementi.
- da 10 elementi a 16
- da 16 elementi a 25
- dalle 25 alle 38
- da 38 a 58
- da 58 a 88
- da 88 a 133 (secondo la formula (dimensione dell'Old Array * 1,5) + 1)
ArrayList<Car> cars = new ArrayList<>(100);
Ora un array di 100 elementi verrà immediatamente allocato in memoria, il che sarà più efficiente perché le risorse non verranno sprecate nell'espansione. C’è anche l’altro lato della medaglia. Quando gli oggetti vengono rimossi ArrayList
dall'array interno, la dimensione non viene ridotta automaticamente. Ad esempio, abbiamo ArrayList
un array interno di 88 elementi, che è completamente riempito: durante il funzionamento del programma, ne rimuoviamo 77 e ne rimangono solo 11: hai già indovinato qual è il problema? Uso inefficiente della memoria, ovviamente! Usiamo solo 11 celle, mentre abbiamo memoria allocata per 88 elementi: 8 volte più del necessario! Per eseguire l'ottimizzazione in questo caso, puoi utilizzare un metodo di classe speciale ArrayList
- trimToSize()
. "Taglia" la lunghezza dell'array interno al numero di elementi attualmente memorizzati in esso. Ora viene allocata tutta la memoria necessaria! :)
GO TO FULL VERSION