2011-01-31 1 views
6

nie mogę modyfing element listy w ten sposób:iteracji listy <String> z modyfing String

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

Po wykonaniu tego kodu elementy tej liście są niezmienione Jak osiągnąć iteracji z modyfing poprzez listy w najprostszym droga.

Odpowiedz

2

Łańcuchy Java są niezmienne, dlatego nie można ich modyfikować. Ponadto, jeśli chcesz zmodyfikować listę, użyj interfejsu iteratora.

+1

Jedyną modyfikacją dozwoloną przez interfejs Iterator jest usunięcie. Natomiast interfejs ListIterator ma metody set() i add(). –

+0

Masz oczywiście rację, jasne wyjaśnienie. –

11

Od obiekty są niezmienne, nie można zmienić wartości, które są iteracyjne. Co więcej, nie można modyfikować listy, która jest iterowana w takiej pętli. Jedynym sposobem, aby to zrobić jest iteracyjne nad indeksów lista ze standardowej pętli lub korzystać z interfejsu 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

Nie, użycie indeksu listy nie jest jedynym sposobem i dostęp, na przykład długo połączona lista z indeksem elementów może działać bardzo słabo. Jeśli chcesz iterować i jednocześnie modyfikować listę, używanie Iteratora lub ListIteratora jest lepsze. – jarnbjo

+0

, więc wróciłem tutaj, jak myślałem, do standardowej pętli. – j2j

+0

@jarnbjo: Masz rację; Jeszcze nie skończyłem. Obejmowałem obie metody. – Gabe

1

W swojej pętli jesteś po prostu zmieniając lokalną kopię napisu. Lepszą alternatywą byłoby użycie iteratora listy i zastąpienie aktualnej pozycji listy.

Edytuj, Ups, sposób na zwolnienie.

1

Nie można zmodyfikować String element w List w ten sposób, ale StringBuilder będzie działać dobrze:

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

To samo odnosi się do innych prymitywne vs sytuacjach referencyjnych oraz for-each pętli. W pętli Iterable jest niezmienny, ale stan elementów w nim nie jest - prymitywy (takie jak String) nie mają stanu i dlatego modyfikujesz tylko lokalną kopię, ale odniesienia mogą mieć stan, a więc możesz je zmutować za pomocą dowolnych metod mutacji, które mogą mieć (np. sb.append("x")).

3

Struny są niezmienne bestie, więc mogę polecić do tej filozofii i utworzyć nową listę zamiast modyfikację jednej:

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

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

wierzę, że to sprawi, że kod łatwiejszy do zrozumienia i utrzymania.

+0

ciekawy pomysł. – j2j

+0

Lista jest modyfikowalna, więc nie ma potrzeby tworzenia nowej. – finnw

+0

@finnw: możesz po prostu udawać, że to nie jest modyfikowalne :) lub jeśli chcesz, możesz uczynić to niemodyfikowalnym w ten sposób: 'Collections.unmodifiableList (list)'. Po prostu zachęcam w tej odpowiedzi, aby napisać więcej kodu wolnego od skutków ubocznych. – tenshi

2

Jak inni zwrócili uwagę:

  • Nie można modyfikować ciągów w Javie, więc s = "x" + s stworzy nowy ciąg (które nie będą zawarte w liście)
  • Nawet jeśli można, zmienna s jest zmienną lokalną, która po przypisaniu jej nie wpływa na wartości zawarte na liście.

Rozwiązaniem jest w tym przypadku użycie StringBuilder która reprezentuje ciąg której może faktycznie zmodyfikować lub użyć ListIterator jako @Michael Borgwardt i @jarnbjo wskazuje.


Korzystanie z 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"); 

Używanie 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

Wolę używać 'for' z iteratorami (podzielone na wiele linii). 'while' to prawie to samo, ale iterator ma duży zakres. I nawiasy klamrowe, oczywiście. –

+0

Ah, dobra uwaga. – aioobe

3

Coś jak to powinno załatwić 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

Dlaczego zadeklarować dodatkową zmienną lokalną 's' i dlaczego ją" ostateczną "? – aioobe

+1

@aioobe: Z przyzwyczajenia; Staram się ogłosić wszystko jako "ostateczne", chyba że jest inaczej. Podobnie ze zmiennymi. Poza tym uwielbiam robić tych, którzy robią przedwczesne optymalizacje. ;) –

+0

Hahah, wystarczy! – aioobe