ejemplo - Una forma rápida y fácil de unir elementos de matriz con un separador(lo opuesto a división) en Java
string array java 8 (15)
"Estoy seguro de que hay una forma certificada y eficiente de hacerlo (¿Apache Commons?)"
si, aparentemente es
StringUtils.join(array, separator)
Esta pregunta ya tiene una respuesta aquí:
- Java: ¿Función para matrices como la combinación PHP ()? 22 respuestas
Ver pregunta relacionada con .NET
Estoy buscando una manera rápida y fácil de hacer exactamente lo opuesto a la división, de modo que cause que ["a","b","c"]
convierta en "a,b,c"
Iterar a través de una matriz requiere agregar una condición (si este no es el último elemento, agregar el separador) o usar una subcadena para eliminar el último separador.
Estoy seguro de que hay una forma certificada y eficiente de hacerlo (¿Apache Commons?)
¿Cómo prefieres hacerlo en tus proyectos?
Aún más fácil, puedes usar Arrays, así obtendrás una Cadena con los valores de la matriz separados por un ","
String concat = Arrays.toString(myArray);
así que terminarás con esto: concat = "[a, b, c]"
Actualizar
Luego puedes deshacerte de los paréntesis usando una subcadena como lo sugiere Jeff
concat = concat.substring(1, concat.length() -1);
entonces terminas con concat = "a, b, c"
Con Java 1.8 hay una nueva clase StringJoiner , por lo que no es necesario usar Guava o Apache Commons:
String str = new StringJoiner(",").add("a").add("b").add("c").toString();
O usando una colección directamente con la nueva secuencia de api:
String str = Arrays.asList("a", "b", "c").stream().collect(Collectors.joining(","));
El enfoque que he adoptado ha evolucionado desde Java 1.0 para proporcionar legibilidad y mantener opciones razonables para la compatibilidad con versiones anteriores de Java, mientras que también proporciona firmas de métodos que son reemplazos directos para aquellos de apache commons-lang. Por motivos de rendimiento, puedo ver algunas posibles objeciones al uso de Arrays.asList, pero prefiero los métodos de ayuda que tienen valores predeterminados razonables sin duplicar el método que realiza el trabajo real. Este enfoque proporciona puntos de entrada apropiados para un método confiable que no requiere conversiones de matriz / lista antes de llamar.
Las posibles variaciones para la compatibilidad de la versión Java incluyen sustituir StringBuffer (Java 1.0) por StringBuilder (Java 1.5), cambiar el iterador de Java 1.5 y eliminar el comodín genérico (Java 1.5) de la Colección (Java 1.2). Si desea llevar la compatibilidad con versiones anteriores un paso o dos más, elimine los métodos que usan Collection y mueva la lógica al método basado en matriz.
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();
}
Esta opción es rápida y clara:
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);
}
Esta pequeña función siempre es útil.
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();
}
Prefiero las colecciones de Google sobre las StringUtils de Apache para este problema en particular:
Joiner.on(separator).join(array)
En comparación con StringUtils, la API Joiner tiene un diseño fluido y es un poco más flexible, por ejemplo, null
elementos null
pueden ser omitidos o reemplazados por un marcador de posición. Además, Joiner
tiene una función para unir mapas con un separador entre clave y valor.
Puede usar reemplazar y reemplazar todo con expresiones regulares.
String[] strings = {"a", "b", "c"};
String result = Arrays.asList(strings).toString().replaceAll("(^//[|//]$)", "").replace(", ", ",");
Debido a que Arrays.asList().toString()
produce: "[a, b, c]", hacemos un replaceAll
para eliminar el primer y último corchete y luego (opcionalmente) puede cambiar la secuencia "," para "," (tu nuevo separador).
Una versión despojada (menos caracteres):
String[] strings = {"a", "b", "c"};
String result = ("" + Arrays.asList(strings)).replaceAll("(^.|.$)", "").replace(", ", "," );
Las expresiones regulares son muy poderosas, especialmente los métodos de cadena "replaceFirst" y "replaceAll". Dales una oportunidad.
Si estás en Android, puedes TextUtils.join(delimiter, tokens)
Todas estas otras respuestas incluyen la sobrecarga del tiempo de ejecución ... como usar ArrayList.toString (). ReplaceAll (...) que son muy inútiles.
Te daré el algoritmo óptimo con cero sobrecarga; no se ve tan bonito como las otras opciones, pero internamente, esto es lo que están haciendo todos (después de las pilas de otras comprobaciones ocultas, la asignación de múltiples matrices y otras cosas crudas).
Como ya sabe que está tratando con cadenas, puede guardar un montón de asignaciones de matrices realizando todo manualmente. Esto no es bonito, pero si rastrea las llamadas de método reales realizadas por las otras implementaciones, verá que tiene la menor sobrecarga de tiempo de ejecución posible.
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);
}
Una solución rápida y sencilla sin ningún tercero incluido.
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();
}
Usando Java 8 puedes hacer esto de una manera muy limpia:
String.join(delimiter, elements);
Esto funciona de tres maneras:
1) Especificando directamente los elementos.
String joined1 = String.join(",", "a", "b", "c");
2) utilizando matrices
String[] array = new String[] { "a", "b", "c" };
String joined2 = String.join(",", array);
3) usando iterables
List<String> list = Arrays.asList(array);
String joined3 = String.join(",", list);
De hecho, Apache Commons Lang tiene un método StringUtils.join
que conectará matrices String
con un separador específico.
Por ejemplo:
String[] s = new String[] {"a", "b", "c"};
String joined = StringUtils.join(s, ","); // "a,b,c"
Sin embargo, sospecho que, como usted menciona, debe haber algún tipo de procesamiento condicional o de subcadenas en la implementación real del método mencionado anteriormente.
Si tuviera que realizar la unión de String
y no tuviera ninguna otra razón para usar Commons Lang, probablemente haría mi propio rollo para reducir el número de dependencias a bibliotecas externas.
public String join(String[] str, String separator){
String retval = "";
for (String s: str){ retval+= separator + s;}
return retval.replaceFirst(separator, "");
}