2009-10-29 12 views
9

Nunca he encontrado una forma clara (n) de hacer lo siguiente.¿Cuál es la manera más elegante de concatenar una lista de valores con delimitador en Java?

Di que tengo una lista/matriz de cadenas.

abc 
def 
ghi 
jkl 

Y quiero para concatenar en una sola cadena delimitada por una coma de la siguiente manera:

abc,def,ghi,jkl 

En Java, si escribo algo como esto (perdón por la sintaxis),

String[] list = new String[] {"abc","def","ghi","jkl"}; 
String str = null; 
for (String s : list) 
{ 
    str = str + s + "," ; 
} 

System.out.println(str); 

voy a

abc,def,ghi,jkl, //Notice the comma in the end 

, así que tengo que volver a escribir lo anterior para el lazo de la siguiente manera

... 
for (int i = 0; i < list.length; i++) 
{ 
    str = str + list[i]; 
    if (i != list.length - 1) 
    { 
    str = str + ","; 
    } 
} 
... 

se puede hacer esto de una manera más elegante en Java?

Definitivamente usaría un StringBuilder/Buffer para mayor eficiencia, pero quería ilustrar el caso sin ser demasiado detallado. Por elegante, me refiero a una solución que evita la fea (?) if verificación dentro del bucle.

+1

Ver http://stackoverflow.com/questions/205555/the-most-sophisticated-way-for-creating-comma-separated-strings-from-a -collection/205712 # 205712 – gimel

+0

http://stackoverflow.com/questions/285523 – toolkit

Respuesta

10

Aquí está mi versión: Java Tricks: Fastest Way to Collecting Objects in a String

StringBuilder buffer = new StringBuilder(); 
String delim = ""; 
for (Object o: list) 
{ 
    buffer.append (delim); 
    delim = ", "; // Avoid if(); assignment is very fast! 
    buffer.append (o); 
} 
buffer.toString(); 

Como un beneficio adicional: Si el código en el bucle es más compleja, a continuación, este enfoque producirá un correctas resultados sin complejos if() s.

También tenga en cuenta que con las CPU modernas, la asignación solo se realizará en la memoria caché (o probablemente solo en un registro).

Conclusión: Si bien este código parece extraño a primera vista, tiene muchas ventajas.

+1

No es muy bonito: realice una inicialización de delim cada iteración. –

+1

Proporcione su solución en caso de eliminación de su publicación de blog. – guerda

+0

¿Cómo es que() no es rápido? –

2

vistazo aquí:

http://snippets.dzone.com/posts/show/91

para una discusión completa de este tema.

+0

Gracias por el enlace. Estoy buscando un enfoque más elegante (tal vez uno que involucre menos líneas de código). El rendimiento, en mi caso, no es una gran preocupación. – Rahul

+0

No me gustan los cheques en el diseño cuando puede hacerlo fuera de –

-1

Utilizaría un StringBuffer para implementar esta función. String es inmutable así que cada vez que concat dos String s, se crea un nuevo objeto.

más eficiente es el uso de StringBuffer:

String[] list = new String[] {"abc","def","ghi","jkl"}; 
StringBuffer str = new StringBuffer(); 
for (String s : list) { 
    str.append(s); 
    str.append(","); 
} 
str.deleteCharAt(str.length()); 
System.out.println(str); //automatically invokes StringBuffer.toString(); 
+2

: p Se olvidó de la última coma ... –

+0

Maldita sea ... corregida. – guerda

+1

No debe usar StringBuffer donde no es necesario, es seguro para subprocesos y lento, en su lugar utilizaría StringBuilder. También debe eliminar la última coma – codevour

3
StringBuilder builder = new StringBuilder(); 
for (String st: list) { 
    builder.append(st).append(','); 
} 
builder.deleteCharAt(builder.length()); 
String result = builder.toString(); 

No utilizar '+' para contacenations cadena. Es lento.

+0

Falta la parathesis derecha en la línea 5;) – guerda

+0

¡Gracias por la corrección! –

+0

¡Me gusta! =) – codevour

-1
for (int i = 0; i < list.length-1; i++) { 
    str = str + list[i]; 
    str = str + ",";  
} 
str = str + list[list.length-1] 
+0

Usar la concatinación de cuerdas no es muy rápido. Este código también es difícil de leer, creo que – codevour

+1

sé que la concatenación de cadenas no es tan rápida, y sí, es menos legible, solo señala otras opciones para hacer lo que pidió OP – Peter

+0

¿Has probado el código con una lista vacía? –

2

Apostaría que hay varias clases denominadas "StringUtil", "StringsUtil", "cadenas" o algo por el estilo en la ruta de clase de cualquier proyecto Java tamaño mediano. Lo más probable es que cualquiera de ellos proporcione una función de unión.He aquí algunos ejemplos que he encontrado en mi proyecto:

org.apache.commons.lang.StringUtils.join(...) 
org.apache.wicket.util.string.Wicket.join(...) 
org.compass.core.util.StringUtils.arrayToDelimitedString(...) 

Como es posible que desee deshacerse de algunas dependencias externas en el futuro, puede que desee a algo como esto:

public static final MyStringUtils { 
    private MyStringUtils() {} 

    public static String join(Object[] list, String delim) { 
     return org.apache.commons.lang.StringUtils.join(list, delim); 
    } 
} 

ahora que es lo que llamo "elegante";)

+0

¿Por qué crear una nueva clase solo para envolver una llamada a org.apache.commons.lang.StringUtils.join? ¿Cómo elimina eso las dependencias externas? –

+1

@DerekSpringer no elimina la dependencia externa. Ocultar la dependencia en algo como MyStringUtils solo hace que sea más fácil cambiar la implementación. Como consecuencia, uno podría eliminar la dependencia externa cambiando solo la clase MyStringUtils. – sfussenegger

11

Usando Guava's (formerly google-collections) joiner class:

Joiner.on(",").join(list) 

Hecho.

+2

+1 para google-collections. Sí, sí, lo sé - 'una dependencia externa solo para unir cadenas?!?!' - pero puede hacer que su código sea mucho más corto + más expresivo que, si aprende la API, se amortizará en una hora. :) – Cowan

+2

una vez que eche un vistazo a la api, usará ist para mucho más que simplemente unir cadenas. –

+0

@Andreas, sugerencias de para qué más sirve? –

0

verificación si esto es útil:

List<Integer> numbers=new ArrayList<Integer>(); 
    numbers.add(1); 
    numbers.add(2); 
    numbers.add(3); 
    numbers.add(4); 
    numbers.add(5); 
    numbers.add(6); 
    String str = " "; 
    for(Integer s:numbers){ 
    str=str+s+" , "; 
    } 
    System.out.println(str.substring(0,str.length()-2)); 
Cuestiones relacionadas