Domanda

    

Questa domanda ha già una risposta qui:

         

Ok, quindi sto tentando di scorrere una ArrayList e rimuovere un elemento specifico. Tuttavia, sto riscontrando dei problemi nell'uso della struttura simile a For-Each. Quando eseguo il seguente codice:

ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)

for(String t : arr)
{
  t = " some other value "; //hoping this would change the actual array
}

for(String t : arr)
{
  System.out.println(t); //however, I still get the same array here
}

La mia domanda in, come posso fare 't' un puntatore a 'arr' in modo da poter cambiare i valori in un ciclo for-each? So che potrei scorrere l'ArrayList usando una struttura diversa, ma questa sembra così pulita e leggibile, sarebbe bello poter rendere 't' un puntatore.

Tutti i commenti sono apprezzati! Anche se dici che dovrei semplicemente succhiarlo e usare un costrutto diverso.

È stato utile?

Soluzione

Penso che l'approccio migliore potrebbe essere quello di utilizzare un ciclo for.

    ArrayList<String> arr = new ArrayList<String>();

    for (int i = 0; i < arr.size(); i++) {

        String t = arr.get(i);

        if (// your condition is met) {
            arr.set(i, "your new value");
        }
    }

Altri suggerimenti

Il problema è che stai provando a cambiare il riferimento t con ambito loop per lasciarlo puntare a una nuova istanza String. Questo non funzionerà. Non fa riferimento alla voce effettiva nell'arraylist. Devi modificare il valore effettivo del riferimento. Se String fosse mutabile e fornisse un metodo fittizio set () , in teoria potresti farlo

for (String t : arr) {
    t.set("some other value");
}

o giù di lì, ma non è possibile in quanto è immutabile. Meglio ottenere un handle dell'entrypoint nell'array stesso usando il normale ciclo for :

for (int i = 0; i < arr.size(); i++) {
    arr.set(i, "some other value");
}

Se insisti nell'uso del ciclo for migliorato, devi sostituire String con StringBuilder , che è modificabile:

for (StringBuilder t : arr) {
     t.delete(0, t.length()).append("some other value");
}

Ricorda, Java è pass-by-value, non pass-by-reference.

Per-ciascuno non ti dà un puntatore indice, quindi non puoi semplicemente usarlo per cambiare un valore immutabile.

Utilizza un ciclo for con un indice o usa un tipo mutabile (come StringBuffer, non String)

Un array di oggetti (come stringhe) in Java è un blocco contiguo contenente una serie ordinata di riferimenti. Pertanto, quando si dispone di un array di 4 stringhe, ciò che realmente si ha sono 4 riferimenti memorizzati nell'array e 4 oggetti stringa che si trovano all'esterno dell'array ma a cui fanno riferimento i suoi 4 elementi.

Quello che fa il costrutto for-each in Java è creare una variabile locale e, per ogni iterazione, copiare in quella variabile locale il riferimento dalla cella dell'array che corrisponde a quella iterazione. Quando imposti la variabile loop ( t = " qualche altro valore " ) stai inserendo un riferimento a una nuova stringa, " qualche altro valore " , nel locale variabile t, non nella matrice.

I contrasti con alcune altre lingue (come Perl) in cui la variabile loop si comporta come un alias dell'elemento array / list stesso.

Il tuo codice viene riscritto dal compilatore come qualcosa del genere:

ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)

for (final Iterator <String> i = arr.iterator(); i.hasNext();) {
    String t;

    t = i.next();
    t = " some other value "; // just changes where t is pointing
}

Per fare quello che vuoi, dovresti scrivere il ciclo for in questo modo:

for (final ListIterator<String> i = arr.iterator(); i.hasNext();) {
     final String t;

     t = i.next();
     i.set("some other value");
}

Iterator non ha il metodo set, solo ListIterator.

Fondamentalmente si desidera rimuovere la stringa t dall'elenco arr. Basta fare un arr.remove (t) e potresti aver finito. Ma non puoi farlo mentre stai ripetendo lo stesso elenco. Otterrai un'eccezione se provi a modificare l'elenco in questo modo.

Hai due opzioni:

  1. clonare l'elenco, scorrere il clone e rimuovere la stringa "specifica" dall'elenco originale
  2. crea un elenco per eliminare i candidati, aggiungi tutte le stringhe "specifiche" a tale elenco e, dopo aver ripetuto l'elenco originale, esegui l'iterazione nel cestino e rimuovi tutto ciò che hai raccolto qui dall'elenco originale.

L'opzione 1 è il facilitatore, il clone può essere creato come:

List<String> clone = new ArrayList<String>(arr);

Sembra che tu capisca male come funzionano gli oggetti / i riferimenti in Java, il che è piuttosto fondamentale per usare il linguaggio in modo efficace. Tuttavia, questo codice qui dovrebbe fare quello che vuoi (scusa per la mancanza di spiegazioni):

ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)

for(int i = 0; i < arr.size(); i++)
{
  arr.set(i, " some other value "); // change the contents of the array
}

for(String t : arr)
{
  System.out.println(t); 
}

Credo che questo non sia correlato a immutabile o mutevole.

 t = " some other value "; //hoping this would change the actual array

t non contiene il riferimento all'oggetto reale. Java copia il valore dall'arraylist e lo inserisce in t in modo che il valore dell'elenco di array non abbia effetto.

HTH

Questa è stata risposta bene. Ecco ancora il mio suggerimento. La variante all'interno del loop è visibile solo lì. Non sarà visto al di fuori del ciclo. Puoi fare t.set () se non fosse String .

Usa un StringBuffer piuttosto che semplici stringhe. In questo modo la stringa all'interno è mutabile.

Le stringhe sono immutabili. Se avessi un tipo mutabile come StringBuilder / Buffer, potresti cambiare la stringa nella tua iterazione. Hai dei riferimenti, ricorda.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top