2009-11-30 11 views
7

Ok, quindi sto cercando di scorrere un'arraylist e rimuovere un elemento specefic. Tuttavia, sto riscontrando dei problemi nell'usare la struttura For-Each like. Quando eseguo il seguente codice:Per-Ognuno e puntatori in Java

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 che io sono in grado di modificare 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 essere in grado di fare un puntatore.

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

+3

non si tratta di foreach loop, questo è un malinteso più basilare di come funziona java – skaffman

+2

Anche se ArrayList è supportato da una matrice: ArrayList! = Array. Non confondersi mescolando i termini (come nei tuoi commenti) –

+1

http://stackoverflow.com/questions/589433/understanding-for-each-loop-in-java –

risposta

16

Credo 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"); 
     } 
    } 
+0

Funziona? No ConcurrentModificationException in questo modo? –

+2

Penso che otterrai questa eccezione solo se aggiungi/rimuovi elementi dall'array mentre iterating –

+0

Sì, certo, non stai più utilizzando l'iteratore, solo un ciclo normale. Non ho prestato attenzione;) –

-5

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

+13

Questo non ha nulla a che vedere con 'String' o 'StringBuilder' o immutabilità, si tratta di come i riferimenti agli oggetti funzionano in Java. – skaffman

+3

questa risposta è errata al 100% ... – TofuBeer

+0

Il codice assegna alla variabile locale 't', questo non influenzerà il riferimento all'interno di ArrayList. Per cambiare devi chiamare arr.set() come da risposta di MB di seguito. – SimonJ

1

Per-each non fornisce un puntatore indice, quindi non è possibile utilizzarlo per modificare un valore immutabile.

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

0

In pratica si desidera rimuovere la stringa t dall'elenco arr. Basta fare un arr.remove (t) e si potrebbe fare. Ma non è possibile eseguire l'operazione mentre si itera sullo stesso elenco. Otterrai un'eccezione se provi a modificare l'elenco in questo modo.

si hanno due opzioni:

  1. clone vostra lista, scorrere l'clone e rimuovere la stringa 'specifica' dalla lista originale
  2. creare una lista di candidati cancellare, aggiungere tutte le stringhe 'specifiche' a quella lista e, dopo aver iterato l'elenco originale, scorrere attraverso la pattumiera e rimuovere tutto ciò che hai raccolto qui dalla lista originale.

opzione 1 è l'easist, il clone può essere fatto come:

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

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

Ciò che il costrutto for-each in Java fa è creare una variabile locale e, per ogni iterazione, copiare in quella variabile locale il riferimento dalla cella dell'array che corrisponde a tale iterazione. Quando imposti la variabile di loop (t = " some other value") stai mettendo un riferimento a una nuova stringa, "some other value", nella variabile locale t, non nella matrice.

I contrasti con altri linguaggi (come Perl) in cui la variabile di ciclo si comporta come un alias per l'elemento matrice/elenco stesso.

+0

+1 per una spiegazione sorprendente! – Hassan

0

Sembra che tu abbia frainteso il modo in cui gli oggetti/i riferimenti funzionano in Java, il che è fondamentale per utilizzare efficacemente il linguaggio.Tuttavia, questo codice qui dovrebbe fare quello che vuoi (scuse per la mancanza di spiegazione):

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); 
} 
5

Il problema è che si sta cercando di cambiare il ciclo con ambito di riferimento t facendolo puntare a un nuova istanza String. Questo non funzionerà. Non fa riferimento alla voce effettiva nell'arrayist. È necessario modificare il valore effettivo del riferimento. Se String era mutevole e fornito un metodo di set() fittizia per questo, si potrebbe in teoria fare

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

o giù di lì, ma non è possibile in quanto si è immutabile. Meglio ottenere una maniglia della entrypoint nella matrice stessa usando il normale for ciclo:

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

Se ti ostini a usare la maggiore for ciclo, allora è necessario sostituire String da StringBuilder, che è mutevole:

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

Ricordare che Java è un valore pass-by, non un riferimento pass-by.

+0

Peggio ancora - la sua prima frase ci dice che vuole rimuovere qualcosa (ha senso, sembra essere il vero incarico per l'esempio.buab-utente-gruppo;)) ma il suo codice mostra una sostituzione ... questo sta per essere una notte loooooong :) –

+0

Wtf, voleva ** rimuovere ** esso. Lì hai bisogno del santo Iterator per. – BalusC

1

Il codice viene riscritta dal compilatore come qualcosa di simile a questo:

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 che avrebbe dovuto 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 fa non ha il metodo set, fa solo ListIterator.

0

Credo, questo non è correlato a immutabile o mutabile.

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

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

HTH

+0

che in realtà è più simile a quello che pensavo in origine. Mi stavo chiedendo se potevo ottenere un riferimento all'oggetto, ma dal momento che è immutabile immagino che non importi comunque. –

0

Questa è stata una risposta soddisfacente. Ancora qui è il mio suggerimento. Il var t loop interno è visibile solo lì. Non sarà visto al di fuori del circuito. Potresti fare t.set() se non fosse String.

0

Utilizzare un StringBuffer anziché stringhe semplici. In questo modo la stringa all'interno è mutabile.