2011-01-31 14 views
6

Non posso modyfing elemento della lista in questo modo:Iterazione della Lista <String> con modyfing String

for (String s : list) 
{ 
    s = "x" + s; 
} 

Dopo l'esecuzione questi elementi di codice di questa lista sono invariati Come realizzare l'iterazione con modyfing attraverso List nel più semplice modo.

risposta

2

Le stringhe Java sono immutabili, quindi non possono essere modificate. Inoltre, se si desidera modificare un elenco, utilizzare l'interfaccia iteratore.

+1

L'unica modifica consentita dall'interfaccia Iterator è la cancellazione. L'interfaccia ListIterator, d'altra parte, ha metodi set() e add(). –

+0

Ovviamente hai ragione, buon chiarimento. –

11

Poiché gli oggetti String non sono modificabili, non è possibile modificare i valori su cui si sta iterando. Inoltre, non è possibile modificare l'elenco su cui si sta iterando in tale ciclo. L'unico modo per farlo è quello di iterare gli indici della lista con un ciclo standard o utilizzare l'interfaccia ListIterator:

for (int i = 0; i < list.size(); i++) 
{ 
    list.set(i, "x" + list.get(i)); 
} 

for (ListIterator i = list.listIterator(); i.hasNext();) 
{ 
    i.set("x" + i.next()); 
} 
+0

No, utilizzare l'indice di elenco non è l'unico modo e accedere ad es. una lunga lista concatenata con un indice di elementi può avere un rendimento molto scarso. Se si desidera ripetere e allo stesso tempo modificare un elenco, utilizzare un Iterator o ListIterator è meglio. – jarnbjo

+0

quindi torno qui come ho pensato al ciclo standard. – j2j

+0

@jarnbjo: hai ragione; Non avevo ancora finito. Ho incluso entrambi i metodi. – Gabe

1

Nel suo ciclo si sta solo modificando la copia locale della stringa. Un'alternativa migliore sarebbe utilizzare l'iteratore dell'elenco e sostituire la posizione corrente dell'elenco.

Modifica, Oops, modo per rallentare.

1

Non è possibile modificare un elemento di un StringList in quel modo, ma un StringBuilder avrebbe funzionato bene:

for (StringBuilder sb : list) sb.append("x"); 

Lo stesso vale per altri primitivo vs situazioni di riferimento e il per-ogni ciclo. Nel loop, Iterable è immutabile, ma lo stato degli elementi in esso non è - primitive (come String) non hanno stato e quindi si sta solo modificando una copia locale, ma i riferimenti possono avere lo stato e quindi è possibile modificarli tramite qualsiasi metodo di mutatore che potrebbero avere (ad esempio, sb.append("x")).

3

Le stringhe sono immutabili bestie, quindi posso consigliare di seguire questa filosofia e creare nuova lista invece modificando uno:

List<String> mappedList = new ArrayList<String>(); 

for (String s : list) { 
    mappedList.add("x" + s); 
} 

Credo che questo renderà il codice più facile da capire e da mantenere.

+0

idea interessante. – j2j

+0

L'elenco è modificabile, quindi non è necessario crearne uno nuovo. – finnw

+0

@finnw: puoi semplicemente fingere che non sia modificabile :) o se vuoi, puoi renderlo immodificabile in questo modo: 'Collections.unmodifiableList (list)'. Io incoraggio solo in questa risposta a scrivere più codice libero effetto collaterale. – tenshi

2

Come altri hanno fatto notare:

  • Non è possibile modificare le stringhe in Java, quindi s = "x" + s creerà una nuova stringa (che non saranno contenuti nella lista)
  • Anche se si potesse, la variabile s è una variabile locale che, se assegnata a, non influisce sui valori contenuti nell'elenco.

La soluzione è in questo caso di utilizzare un StringBuilder che rappresenta una stringa che si può effettivamente modificare o utilizzare un ListIterator come @ Michael Borgwardt e @jarnbjo sottolinea.


Utilizzando un StringBuilder:

List<StringBuilder> someStrings = new LinkedList<StringBuilder>(); 
someStrings.add(new StringBuilder("hello")); 
someStrings.add(new StringBuilder("world")); 

for (StringBuilder s : someStrings) 
    s.insert(0, "x"); 

Utilizzando un ListIterator:

List<String> someStrings = new LinkedList<String>(); 
someStrings.add("hello"); 
someStrings.add("world"); 

for (ListIterator<String> iter = someStrings.listIterator(); iter.hasNext();) 
    iter.set("x" + iter.next()); 

ideone.com demo

+0

Preferisco usare 'for' con gli iteratori (divisi su più righe). 'while' sono più o meno la stessa cosa, ma l'iteratore ha uno scopo molto ampio. E bretelle, ovviamente. –

+0

Ah, buon punto. – aioobe

3

Qualcosa di simile dovrebbe fare il jo b:

public static void main(String[] args) throws Exception { 
    final List<String> lst = Arrays.asList("a", "b", "c"); 
    for(final ListIterator<String> iter = lst.listIterator(); iter.hasNext();) { 
     final String s = iter.next(); 
     iter.set(s + "x"); 
    } 
    System.out.println(lst); 
} 
+1

Perché dichiarare una variabile locale extra 's', e perché renderla' final'? – aioobe

+1

@aioobe: per abitudine; Considero un punto dichiarare tutto come "finale" a meno che non sia necessario diversamente. Allo stesso modo con le variabili. Inoltre mi piace fare quelli che fanno rabbrividire prematuramente l'ottimizzazione. ;) –

+0

Hahah, abbastanza giusto! – aioobe

Problemi correlati