2012-05-08 14 views
21

Pracuję na serwerze, który zwraca listy oddzielone znakami do swojego klienta. W celu zbudowania tych list mam do wykrywania pierwszej iteracji za pomocą pętli for-each:Wykrywanie pierwszej iteracji za pomocą pętli for w Javie

StringBuilder builder = new StringBuilder() ; 
    boolean firstIterationFlag = true ; 

    for (String s : list){ 
     if (firstIterationFlag) { 
      firstIterationFlag = false ; 
     } else { 
      builder.append(separator); 
     } 
     builder.append(s) ;   
    } 
    return builder.toString() ; 

Czy istnieje sposób to zrobić bez flagi?

+0

Dlaczego musisz wykryć pierwszą iterację pętli? – BeRecursive

+0

zamiast pętli 'forEach', możesz ręcznie wykonać normalną pętlę' for', zaczynając od indeksu '1' zamiast 0. – Sheriff

+2

Spójrz na to pytanie SO: http://stackoverflow.com/questions/63150/whats-the-best-way-to-build-a-string-of-delimited-items-in-java - może to być lepsze rozwiązanie niż twoje. –

Odpowiedz

18

Jeden prostszy sposób dla tej sytuacji jest, aby pamiętać, że zawsze można dołączyć pusty ciąg:

// For the first iteration, use a no-op separator 
String currentSeparator = ""; 
for (String s : list) { 
    builder.append(currentSeparator); 
    builder.append(s); 
    // From the second iteration onwards, use this 
    currentSeparator = separator; 
} 

Alternatywnie (i preferrably) używać Joiner klasę guawy, aby zacząć :)

Ten „stolarskie "Scenariusz jest prawie zawsze ten podany dla tego wymogu - więc po prostu użyj Joiner. W przypadku innych scenariuszy użyj zwykłej pętli for lub użyj warunku zgodnie z kodem.

+1

+1 dla łącznika, -1 dla currentSeparator = +0 :-) –

+1

Usunięto "if", ale trudniej było uchwycić –

+1

+1 dla currentSeparator;) –

6

Nie używając foreach, ale ręcznie za pomocą iteratora:

Iterator<String> it = list.iterator(); 
if(it.hasNext()){ 
    doSomeThingForTheFirstTime(it.next()); 
    while(it.hasNext()){ 
     doSomethingElse(it.next); 
    } 
} 

(btw, to jest dość dużo, co klasa guawy za Joiner robi wewnętrznie, choć na wyższym poziomie)

3

W konkretnym przypadku Ci cytować, użyj Guava na Joiner zamiast toczenia własne ...

przedmiot, który dołącza do fragmentów tekstu (określona jako tablica, iterable, varargs lub nawet mapa) z separatorem. Albo dołącza wyniki do Appendable, albo zwraca je jako String. Przykład:

Joiner joiner = Joiner.on(separator).skipNulls(); 
return joiner.join(list); 
+1

+1 (Guava's Joiner jest znacznie lepszy od wszystkiego w Apache commons) –

0

Można też użyć następującej metody:

public static String toString(List<?> list, String separator) { 
    StringBuilder sb = new StringBuilder(); 
    Iterator<?> it = list.iterator(); 
    while (it.hasNext()) { 
     Object next = it.next(); 
     sb.append(next); 
     if (it.hasNext()) { 
      sb.append(separator); 
     } 
    } 
    return sb.toString(); 
} 

Udoskonalony for stwierdzenie jest równoznaczne z podstawowego for zestawienia w postaci:

for (I #i = Expression.iterator(); #i.hasNext();) { 
    VariableModifiersopt TargetType Identifier = 
     (TargetType) #i.next(); 
    Statement 
} 

#i jest automatycznie wygenerowany identyfikator

1

Dla zabawy tutaj jest inna opcja.

StringBuilder builder = new StringBuilder(); 
    for (String s : list) { 
     builder.append(separator); 
     builder.append(s); 
    } 
    builder.deleteCharAt(0); 
    return builder.toString(); 
0

Cóż, nie wykryje to pierwszej iteracji w pętli, ale rozwiąże problem. Wystarczy dołączyć seperator na końcu każdego ciągu i odciąć ostatni separator.

StringBuilder builder = new StringBuilder() ; 

for (String s : list) { 
    builder.append(s) ;   
    builder.append(separator); 
} 
builder.setLength(builder.length() - separator.length()); 
return builder.toString() ; 
0

Można spróbować tego :)

int i = 0; 
for (something : manythings) { 
    i++; 
} 
1

Java 8 Rozwiązanie

Jeśli masz Java 8 dostępny, można po prostu użyć String#join, nie ma potrzeby Guava:

String.join(", ", list) 
Powiązane problemy