Ultima iterazione di enhanced for loop in java

C’è un modo per determinare se il ciclo sta iterando per l’ultima volta. Il mio codice è simile a questo:

int[] array = {1, 2, 3...}; StringBuilder builder = new StringBuilder(); for(int i : array) { builder.append("" + i); if(!lastiteration) builder.append(","); } 

Ora il fatto è che non voglio aggiungere la virgola nell’ultima iterazione. Ora c’è un modo per determinare se è l’ultima iterazione o sono bloccato con il ciclo for o usando un contatore esterno per tenere traccia.

Un’altra alternativa è quella di aggiungere la virgola prima di aggiungere i, solo non sulla prima iterazione. (Per favore non usare "" + i , a proposito – non si vuole veramente la concatenazione qui, e StringBuilder ha un sovraccarico app (int) perfettamente buono).

 int[] array = {1, 2, 3...}; StringBuilder builder = new StringBuilder(); for (int i : array) { if (builder.length() != 0) { builder.append(","); } builder.append(i); } 

La cosa bella di questo è che funzionerà con qualsiasi Iterable – non puoi sempre indicizzare le cose. (Il “aggiungi la virgola e poi rimuovilo alla fine” è un bel suggerimento quando stai usando StringBuilder – ma non funziona per cose come scrivere sugli stream. Probabilmente è l’approccio migliore per questo problema esatto. )

Un altro modo per farlo:

 String delim = ""; for (int i : ints) { sb.append(delim).append(i); delim = ","; } 

Aggiornamento: per Java 8, ora hai i Collector

Potrebbe essere più facile aggiungere sempre. E poi, una volta terminato il ciclo, rimuovi il carattere finale. Tanti meno condizionali anche in questo modo.

Puoi usare deleteCharAt(int index) StringBuilder con index length() - 1

Forse stai usando lo strumento sbagliato per il lavoro.

Questo è più manuale di quello che stai facendo, ma è in un modo più elegante se non un po ‘”vecchia scuola”

  StringBuffer buffer = new StringBuffer(); Iterator iter = s.iterator(); while (iter.hasNext()) { buffer.append(iter.next()); if (iter.hasNext()) { buffer.append(delimiter); } } 

Questa è quasi una ripetizione di questa domanda StackOverflow . Quello che vuoi è StringUtils e chiamare il metodo join .

 StringUtils.join(strArr, ','); 

Un’altra soluzione (forse la più efficiente)

  int[] array = {1, 2, 3}; StringBuilder builder = new StringBuilder(); if (array.length != 0) { builder.append(array[0]); for (int i = 1; i < array.length; i++ ) { builder.append(","); builder.append(array[i]); } } 

I cicli espliciti funzionano sempre meglio di quelli impliciti.

 builder.append( "" + array[0] ); for( int i = 1; i != array.length; i += 1 ) { builder.append( ", " + array[i] ); } 

Dovresti avvolgere il tutto in un’istruzione if nel caso avessi a che fare con un array a lunghezza zero.

mantienilo semplice e usa un ciclo for standard:

 for(int i = 0 ; i < array.length ; i ++ ){ builder.append(array[i]); if( i != array.length - 1 ){ builder.append(','); } } 

o semplicemente usa apache commons-lang StringUtils.join ()

Se lo converti in un classico indice, sì.

O potresti semplicemente cancellare l’ultima virgola dopo che è stata completata. Così:

 int[] array = {1, 2, 3...}; StringBuilder builder = new StringBuilder(); for(int i : array) { builder.append(i + ","); } if(builder.charAt((builder.length() - 1) == ',')) builder.deleteCharAt(builder.length() - 1); 

Io, io uso solo StringUtils.join() da commons-lang .

Hai bisogno di Class Separator .

 Separator s = new Separator(", "); for(int i : array) { builder.append(s).append(i); } 

L’implementazione di Class Separator è semplice. Include una stringa che viene restituita a ogni chiamata di toString() tranne la prima chiamata, che restituisce una stringa vuota.

Basato su java.util.AbstractCollection.toString (), esce presto per evitare il delimitatore.

 StringBuffer buffer = new StringBuffer(); Iterator iter = s.iterator(); for (;;) { buffer.append(iter.next()); if (! iter.hasNext()) break; buffer.append(delimiter); } 

È efficiente ed elegante, ma non così evidente come alcune delle altre risposte.

Ecco una soluzione:

 int[] array = {1, 2, 3...}; StringBuilder builder = new StringBuilder(); bool firstiteration=true; for(int i : array) { if(!firstiteration) builder.append(","); builder.append("" + i); firstiteration=false; } 

Cerca la prima iterazione 🙂

Ancora un’altra opzione.

 StringBuilder builder = new StringBuilder(); for(int i : array) builder.append(',').append(i); String text = builder.toString(); if (text.startsWith(",")) text=text.substring(1); 

Molte delle soluzioni qui descritte sono un po ‘esagerate, IMHO, specialmente quelle che si basano su librerie esterne. C’è un bel linguaggio pulito e chiaro per ottenere una lista separata da virgola che ho sempre usato. Si basa sull’operatore condizionale (?):

Modifica : soluzione originale corretta, ma non ottimale in base ai commenti. Provando una seconda volta:

  int[] array = {1, 2, 3}; StringBuilder builder = new StringBuilder(); for (int i = 0 ; i < array.length; i++) builder.append(i == 0 ? "" : ",").append(array[i]); 

Ecco qua, in 4 righe di codice che includono la dichiarazione dell'array e lo StringBuilder.

Ecco un benchmark SSCCE che ho eseguito (correlato a ciò che dovevo implementare) con questi risultati:

 elapsed time with checks at every iteration: 12055(ms) elapsed time with deletion at the end: 11977(ms) 

Almeno sul mio esempio, saltare il controllo ad ogni iterazione non è notevolmente più veloce, specialmente per volumi di dati sane, ma è più veloce.

 import java.util.ArrayList; import java.util.List; public class TestCommas { public static String GetUrlsIn(int aProjectID, List aUrls, boolean aPreferChecks) { if (aPreferChecks) { StringBuffer sql = new StringBuffer("select * from mytable_" + aProjectID + " WHERE hash IN "); StringBuffer inHashes = new StringBuffer("("); StringBuffer inURLs = new StringBuffer("("); if (aUrls.size() > 0) { for (String url : aUrls) { if (inHashes.length() > 0) { inHashes.append(","); inURLs.append(","); } inHashes.append(url.hashCode()); inURLs.append("\"").append(url.replace("\"", "\\\"")).append("\"");//.append(","); } } inHashes.append(")"); inURLs.append(")"); return sql.append(inHashes).append(" AND url IN ").append(inURLs).toString(); } else { StringBuffer sql = new StringBuffer("select * from mytable" + aProjectID + " WHERE hash IN "); StringBuffer inHashes = new StringBuffer("("); StringBuffer inURLs = new StringBuffer("("); if (aUrls.size() > 0) { for (String url : aUrls) { inHashes.append(url.hashCode()).append(","); inURLs.append("\"").append(url.replace("\"", "\\\"")).append("\"").append(","); } } inHashes.deleteCharAt(inHashes.length()-1); inURLs.deleteCharAt(inURLs.length()-1); inHashes.append(")"); inURLs.append(")"); return sql.append(inHashes).append(" AND url IN ").append(inURLs).toString(); } } public static void main(String[] args) { List urls = new ArrayList(); for (int i = 0; i < 10000; i++) { urls.add("http://www.google.com/" + System.currentTimeMillis()); urls.add("http://www.yahoo.com/" + System.currentTimeMillis()); urls.add("http://www.bing.com/" + System.currentTimeMillis()); } long startTime = System.currentTimeMillis(); for (int i = 0; i < 300; i++) { GetUrlsIn(5, urls, true); } long endTime = System.currentTimeMillis(); System.out.println("elapsed time with checks at every iteration: " + (endTime-startTime) + "(ms)"); startTime = System.currentTimeMillis(); for (int i = 0; i < 300; i++) { GetUrlsIn(5, urls, false); } endTime = System.currentTimeMillis(); System.out.println("elapsed time with deletion at the end: " + (endTime-startTime) + "(ms)"); } } 

Come menzionato nel toolkit, in Java 8 ora abbiamo Collector . Ecco come sarà il codice:

 String joined = array.stream().map(Object::toString).collect(Collectors.joining(", ")); 

Penso che faccia esattamente quello che stai cercando, ed è un modello che potresti usare per molte altre cose.

Un altro approccio è quello di avere la lunghezza dell’array (se disponibile) memorizzata in una variabile separata (più efficiente di ricontrollare la lunghezza ogni volta). È quindi ansible confrontare il proprio indice con quella lunghezza per determinare se aggiungere o meno la virgola finale.

EDIT: Un’altra considerazione sta pesando il costo delle prestazioni di rimozione di un carattere finale (che può causare una copia di stringa) contro il fatto di essere controllato un condizionale in ogni iterazione.

Se stai trasformando un array in un array delimitato da virgole, molte lingue hanno una funzione join proprio per questo. Trasforma una matrice in una stringa con un delimitatore tra ogni elemento.

In questo caso non c’è davvero bisogno di sapere se è l’ultima ripetizione. Ci sono molti modi in cui possiamo risolvere questo. Un modo sarebbe:

 String del = null; for(int i : array) { if (del != null) builder.append(del); else del = ","; builder.append(i); } 

Due percorsi alternativi qui:

1: Apache Commons String Utils

2: Mantieni un booleano chiamato per first , impostato su true. In ogni iterazione, se first è falso, aggiungi la tua virgola; successivamente, imposta first su false.

Dato che è un array fisso, sarebbe più semplice evitare semplicemente l’enhanced per … Se l’Object è una collezione, un iteratore sarebbe più semplice.

 int nums[] = getNumbersArray(); StringBuilder builder = new StringBuilder(); // non enhanced version for(int i = 0; i < nums.length; i++){ builder.append(nums[i]); if(i < nums.length - 1){ builder.append(","); } } //using iterator Iterator numIter = Arrays.asList(nums).iterator(); while(numIter.hasNext()){ int num = numIter.next(); builder.append(num); if(numIter.hasNext()){ builder.append(","); } }