Un modo semplice e veloce per unire gli elementi dell’array con un separatore (l’opposto della divisione) in Java

Vedi la domanda .NET relativa

Sto cercando un modo semplice e veloce per fare esattamente l’opposto di split in modo che causi ["a","b","c"] per diventare "a,b,c"

L’iterazione attraverso un array richiede l’aggiunta di una condizione (se questo non è l’ultimo elemento, aggiungi il separatore) o l’uso della sottostringa per rimuovere l’ultimo separatore.

Sono sicuro che esiste un modo certificato ed efficiente per farlo (Apache Commons?)

Come preferisci farlo nei tuoi progetti?

Usando Java 8 puoi farlo in un modo molto pulito:

 String.join(delimiter, elements); 

Questo funziona in tre modi:

1) specificando direttamente gli elementi

 String joined1 = String.join(",", "a", "b", "c"); 

2) utilizzando gli array

 String[] array = new String[] { "a", "b", "c" }; String joined2 = String.join(",", array); 

3) utilizzando iterabili

 List list = Arrays.asList(array); String joined3 = String.join(",", list); 

Se sei su Android puoi TextUtils.join(delimiter, tokens)

Preferisco le raccolte Google su Apache StringUtils per questo particolare problema:

 Joiner.on(separator).join(array) 

Rispetto a StringUtils, l’API Joiner ha un design fluente ed è un po ‘più flessibile, ad esempio gli elementi null possono essere saltati o sostituiti da un segnaposto. Inoltre, Joiner ha una funzione per unire mappe con un separatore tra chiave e valore.

Apache Commons Lang ha infatti un metodo StringUtils.join che collegherà gli array di String insieme a un separatore specificato.

Per esempio:

 String[] s = new String[] {"a", "b", "c"}; String joined = StringUtils.join(s, ","); // "a,b,c" 

Tuttavia, sospetto che, come dici tu, ci debba essere un qualche tipo di elaborazione condizionale o di sottostringa nell’implementazione effettiva del metodo sopra menzionato.

Se dovessi eseguire l’unione String e non avessi altri motivi per usare Commons Lang, probabilmente lo avrei fatto per ridurre il numero di dipendenze alle librerie esterne.

Una soluzione semplice e veloce senza terze parti.

 public static String strJoin(String[] aArr, String sSep) { StringBuilder sbStr = new StringBuilder(); for (int i = 0, il = aArr.length; i < il; i++) { if (i > 0) sbStr.append(sSep); sbStr.append(aArr[i]); } return sbStr.toString(); } 

“Sono sicuro che esiste un modo efficace e certificato per farlo (Apache Commons?)”

sì, apparentemente è

 StringUtils.join(array, separator) 

http://www.java2s.com/Code/JavaAPI/org.apache.commons.lang/StringUtilsjoinObjectarrayStringseparator.htm

Ancora più facile puoi usare gli array, quindi otterrai una stringa con i valori dell’array separati da un “,”

 String concat = Arrays.toString(myArray); 

così finirai con questo: concat = “[a, b, c]”

Aggiornare

È quindi ansible sbarazzarsi delle parentesi utilizzando una sottostringa come suggerito da Jeff

 concat = concat.substring(1, concat.length() -1); 

così finisci con concat = “a, b, c”

È ansible utilizzare replace and replaceAll con espressioni regolari.

 String[] strings = {"a", "b", "c"}; String result = Arrays.asList(strings).toString().replaceAll("(^\\[|\\]$)", "").replace(", ", ","); 

Perché Arrays.asList().toString() produce: “[a, b, c]”, facciamo un replaceAll per rimuovere la prima e l’ultima parentesi e poi (facoltativamente) puoi cambiare la sequenza “,” per “,” (il tuo nuovo separatore).

Una versione ridotta (meno caratteri):

 String[] strings = {"a", "b", "c"}; String result = ("" + Arrays.asList(strings)).replaceAll("(^.|.$)", "").replace(", ", "," ); 

Le espressioni regolari sono molto potenti, specialmente i metodi String “replaceFirst” e “replaceAll”. Provali.

Con Java 1.8 c’è una nuova class StringJoiner , quindi non c’è bisogno di Guava o Apache Commons:

 String str = new StringJoiner(",").add("a").add("b").add("c").toString(); 

O utilizzando una raccolta direttamente con la nuova API di streaming:

 String str = Arrays.asList("a", "b", "c").stream().collect(Collectors.joining(",")); 

Tutte queste altre risposte includono sovraccarico di runtime … come usare ArrayList.toString (). ReplaceAll (…) che sono molto dispendiosi.

Ti darò l’algoritmo ottimale con zero overhead; non sembra bello come le altre opzioni, ma internamente, questo è quello che stanno facendo tutti (dopo le pile di altri assegni nascosti, l’assegnazione di più array e altri dettagli).

Dato che sai già che hai a che fare con le stringhe, puoi salvare una serie di allocazioni di array eseguendo tutto manualmente. Questo non è bello, ma se si tracciano le chiamate al metodo effettive effettuate dalle altre implementazioni, si vedrà che è ansible il minimo sovraccarico di runtime.

 public static String join(String separator, String ... values) { if (values.length==0)return "";//need at least one element //all string operations use a new array, so minimize all calls possible char[] sep = separator.toCharArray(); // determine final size and normalize nulls int totalSize = (values.length - 1) * sep.length;// separator size for (int i = 0; i < values.length; i++) { if (values[i] == null) values[i] = ""; else totalSize += values[i].length(); } //exact size; no bounds checks or resizes char[] joined = new char[totalSize]; int pos = 0; //note, we are iterating all the elements except the last one for (int i = 0, end = values.length-1; i < end; i++) { System.arraycopy(values[i].toCharArray(), 0, joined, pos, values[i].length()); pos += values[i].length(); System.arraycopy(sep, 0, joined, pos, sep.length); pos += sep.length; } //now, add the last element; //this is why we checked values.length == 0 off the hop System.arraycopy(values[values.length-1].toCharArray(), 0, joined, pos, values[values.length-1].length()); return new String(joined); } 

Questa opzione è veloce e chiara:

  public static String join(String separator, String... values) { StringBuilder sb = new StringBuilder(128); int end = 0; for (String s : values) { if (s != null) { sb.append(s); end = sb.length(); sb.append(separator); } } return sb.substring(0, end); } 

Questa piccola funzione è sempre utile.

 public static String join(String[] strings, int startIndex, String separator) { StringBuffer sb = new StringBuffer(); for (int i=startIndex; i < strings.length; i++) { if (i != startIndex) sb.append(separator); sb.append(strings[i]); } return sb.toString(); } 

L’approccio che ho adottato si è evoluto da Java 1.0 per fornire leggibilità e mantenere opzioni ragionevoli per la compatibilità con le versioni precedenti di Java, fornendo anche firme di metodi che sono sostituzioni drop-in per quelli da apache commons-lang. Per motivi di prestazioni, sono in grado di vedere alcune possibili obiezioni all’uso di Arrays.asList, ma preferisco metodi di supporto che hanno impostazioni predefinite corrette senza duplicare l’unico metodo che esegue il lavoro effettivo. Questo approccio fornisce punti di accesso appropriati a un metodo affidabile che non richiede conversioni di array / elenco prima della chiamata.

Le possibili varianti per la compatibilità della versione Java includono la sostituzione di StringBuffer (Java 1.0) per StringBuilder (Java 1.5), la rimozione dell’iterazione Java 1.5 e la rimozione del carattere jolly generico (Java 1.5) dalla Collection (Java 1.2). Se si desidera ottenere la retrocompatibilità di uno o più passaggi, eliminare i metodi che utilizzano Collection e spostare la logica nel metodo basato su array.

 public static String join(String[] values) { return join(values, ','); } public static String join(String[] values, char delimiter) { return join(Arrays.asList(values), String.valueOf(delimiter)); } // To match Apache commons-lang: StringUtils.join(values, delimiter) public static String join(String[] values, String delimiter) { return join(Arrays.asList(values), delimiter); } public static String join(Collection values) { return join(values, ','); } public static String join(Collection values, char delimiter) { return join(values, String.valueOf(delimiter)); } public static String join(Collection values, String delimiter) { if (values == null) { return new String(); } StringBuffer strbuf = new StringBuffer(); boolean first = true; for (Object value : values) { if (!first) { strbuf.append(delimiter); } else { first = false; } strbuf.append(value.toString()); } return strbuf.toString(); } 
 public String join(String[] str, String separator){ String retval = ""; for (String s: str){ retval+= separator + s;} return retval.replaceFirst(separator, ""); }