Come si scorre attraverso un array e si elimina un elemento?

3

Ho un array e posso scorrere l'iter. So che è impossibile cambiare la dimensione di un array; tuttavia, come faccio a rimuovere un determinato elemento che non desidero più nell'array?

Esempio: se l'utente sceglie di eliminare un determinato elemento, come faccio a scrivere questo nel mio codice?

    
posta Elijah Hampton 14.03.2015 - 20:50
fonte

3 risposte

6

Il framework Java Collections è qualcosa che dovresti sfogliare. Ci sono anche alcuni tipi che non sono array (Set e Map) ma scoprirai che li userai spesso. Esistono molti tipi diversi di raccolte e alcuni hanno vantaggi rispetto ad altri per determinati tipi di operazioni.

Matrici classiche

Innanzitutto, la cosa che non è nel framework delle collezioni. La matrice. Not ArrayList, ma piuttosto il classico int[] . Il vantaggio dell'array è quello di mappare da vicino la memoria. foo[42] è a cercare. Molte chiamate a livello di sistema che ti forniscono un numero fisso di elementi sono matrici e sono utili. Ad esempio, "1,2,3".split(",") restituisce un array.

Il problema con gli array è che non sono così flessibili. L'aggiunta di un elemento alla fine di un array già presente è la massima capacità significa allocare un nuovo array più grande e quindi eseguire un System.arraycopy() ( javadoc ) per copiare tutti gli elementi da una matrice in un altro array in modo tempestivo.

Per rimuovere un elemento dall'elenco che è necessario rimuoverlo e quindi percorrere il resto dell'elenco per avere di nuovo tutto contagious. Se si desidera rimuovere foo[4] dall'elenco, assegnare quindi foo[4] = foo[5] e foo[5] = foo[6] e così via fino alla fine dell'elenco. Questo è se devi farlo a mano. Puoi anche usare quel System.arraycopy menzionato per farlo per te dato il giusto insieme di argomenti. Qualcosa come:

System.arraycopy(foo,5,foo,4,foo.length - 4);

Potrei aver sbagliato, ma questa è l'idea generale. Copia l'array su se stesso. dovrebbe funzionare.

If the src and dest arguments refer to the same array object, then the copying is performed as if the components at positions srcPos through srcPos+length-1 were first copied to a temporary array with length components and then the contents of the temporary array were copied into positions destPos through destPos+length-1 of the destination array.

Elenchi

Come vedi, gli array sono un po 'scomodi con cui lavorare. Hai fatto tutto a mano. È bello saperlo, ma è un dolore da praticare. Ci sono due liste che sono di uso comune che rendono questo più facile per te. Per la maggior parte, gli elenchi cercano come matrici.

List<Integer> foo = ...;
foo.get(4);
foo.remove(5);

Si chiamano metodi su di essi, ma si sta recuperando il quarto elemento tramite la chiamata al metodo anziché tramite l'accesso diretto attraverso l'array. Vedi che foo.remove(5) . Questo è tutto. Hai finito. Hai rimosso un elemento dall'elenco e cancellato. Molto più facile da ricordare.

ArrayList

ArrayList è supportato da una matrice. Ciò significa che fare foo.get(4) è veloce, ma foo.add(42, foo.size()+1) rischia di essere lento perché deve fare tutto questo movimento per allocare un nuovo elenco (sì, so che l'elenco può essere più lungo della dimensione , ma assumiamo che abbia le stesse dimensioni del suo elenco attuale.

Invece di dover ricordare come fare tutto il mischiare, hai dei buoni metodi per fare il tuo lavoro per te. Ciò non significa che non sia stato fatto (il lavoro è ancora fatto dietro le quinte dell'interfaccia), ma è qualcosa di cui non devi preoccuparti.

Quindi, ArrayList è per:

  • fast get (O (1))
  • rimuovi lentamente e inserisci (O (lunghezza))
  • accoda lento quando è pieno (O (lunghezza))

LinkedList

Per qualche motivo, l'implementazione goto list di tutti è ArrayList. Non so perché. Molte volte, quando lavoro con le liste, la LinkedList è quella più applicabile. Continui ad aggiungere cose fino alla fine. Raramente vuoi l'elemento n th . Vuoi solo iterare su di loro.

Questo è il motivo per cui LinkedList è utile. Rimuove e aggiunge rapidamente e il suo iteratore è veloce quanto ArrayList. È solo se vuoi che foo.get(400) diventi un po 'più lento dell'attrezzo ArrayList.

Anche LinkedList è anche un Deque, ma la gente se ne dimentica. Ciò ti consente di accedere a LinkedList come una coda a doppio attacco (utile per implementare uno stack o una coda).

Quindi, se stai aggiungendo e iterando, la LinkedList è per te.

  • Get è lento (O (indice))
  • Fast append (O (1))
  • Rimuovi e inserisci è lento (O (indice))

Si noti che l'O (indice) contiene un po 'di bit di riconoscimento. Indicherà in base al modo in cui è più veloce arrivare (dalla fine o dall'inizio). Quindi se il LinkedList è lungo 100, e ottieni (10), inizia dall'inizio. Se chiedi di ottenere (90), inizia dalla fine. Quindi ottenere (indice) non è mai più di ottenere (lunghezza / 2), ma questo è tutto solo fattori che non hanno importanza quando si guarda Big O.

    
risposta data 14.03.2015 - 22:08
fonte
1

Se devi farlo davvero usando un array, allora dovrai:

  • copia tutti gli elementi dell'array dopo che l'elemento è stato eliminato da una posizione per coprire l'elemento rimosso.

  • ridimensiona l'array in modo che sia più piccolo di un elemento.

La copia di elementi in una posizione può essere effettuata scrivendo un loop tu stesso o invocando System.arraycopy( src, srcPos, dest, destPos, length) .

Il ridimensionamento dell'array può essere fatto in questo modo: myArray = Arrays.copyOf( myArray, newCapacity ) .

Detto questo, se hai bisogno di manipolare la lunghezza dell'array, allora sicuramente vai con ArrayList invece di usare gli array. Questa ruota è già stata inventata.

    
risposta data 14.03.2015 - 23:19
fonte
0

Se si tratta di una matrice di tipi di riferimento, il contenuto di ogni cella verrà impostato su null . Se hai inserito un valore reale in una cella, puoi effettivamente "eliminarlo" sostituendolo con null . Finché il tuo codice verifica i valori null , la sostituzione con null può essere considerata come una cancellazione. Ma questo è un uso inefficiente degli array, il cui vantaggio principale è la velocità di accesso ai valori indicizzati il cui numero non cambia. Se la tua "collezione" può o meno contenere determinati valori, una mappa o lista sarebbe meglio.

Se si tratta di un array di primitive ( int , byte e così via), non è possibile eliminare i contenuti. Puoi inserire il valore predefinito ( 0 per i tipi numerici, falso per i booleani) ma probabilmente non ti è utile. Il meglio che puoi fare è copiare tutti gli elementi da quello in un nuovo array. Qualcosa che puoi anche fare per i tipi di riferimento copiando tutto ciò che non è null .

Quindi la domanda importante è questa:

  1. Vuoi sapere se un indice di array specifico contiene un valore significativo?

  2. O sei semplicemente interessato a tutti i valori attualmente presenti nell'array?

Se la risposta è 1, per i tipi primitivi la risposta è no . Per i tipi di riferimento potresti sostituirli con null , ma in realtà, una mappa sarebbe migliore perché in tal caso puoi eliminare la chiave.

Se la risposta è 2, puoi copiare tutte le altre celle in un nuovo array.

Quindi qual è?

    
risposta data 14.03.2015 - 22:21
fonte

Leggi altre domande sui tag