Concatenación de cadenas en Java
Une cadenas en Java con el operador +, concat() y StringBuilder, y compara su rendimiento.
"Concatenación" significa unir cadenas de texto una tras otra. Java ofrece varias formas de hacerlo: +, concat, String.format, bloques de texto, StringBuilder y String.join. Difieren en legibilidad y, cuando se usan en bucles, en rendimiento.
El operador +
+ es la forma más habitual:
String first = "Ada";
String last = "Lovelace";
String full = first + " " + last; // "Ada Lovelace"También convierte valores que no son cadenas a string mediante su toString():
int age = 36;
String s = "Age: " + age; // "Age: 36"Internamente, el compilador transforma a + b + c en una única llamada StringBuilder.append(...).append(...).toString(). Por lo tanto, una expresión encadenada con + es eficiente.
concat
String.concat(other) devuelve esta cadena seguida de other:
"Hello, ".concat("World!"); // "Hello, World!"Es prácticamente igual que +, pero solo acepta un String (sin conversión automática). La mayoría del código simplemente usa +.
String.format y formatted
Para concatenar múltiples fragmentos con formato específico por tipo, String.format es más limpio que largas cadenas de +:
String name = "Ada";
int age = 36;
String s = String.format("%s is %d years old", name, age);Desde Java 15, el método de instancia formatted es equivalente y se lee de izquierda a derecha:
"%s is %d years old".formatted(name, age);Bloques de texto para múltiples líneas
Para cadenas de varias líneas, la sintaxis de bloques de texto (Java 15+) evita largas cadenas con \n:
String json = """
{
"name": "%s",
"age": %d
}
""".formatted(name, age);StringBuilder — para bucles
Las cadenas en Java son inmutables: una vez creada, una String nunca puede cambiar. Por eso, cada + sobre una String genera un objeto completamente nuevo. En un bucle con miles de iteraciones, eso supone mucha basura de corta vida y muchas copias. Usa StringBuilder en su lugar: dispone de un único buffer interno mutable que crece en el mismo lugar:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("line ").append(i).append("\n");
}
String result = sb.toString();Los métodos de StringBuilder que más usarás:
append(any)— añade al final (devuelve el propio builder para poder encadenar llamadas).insert(index, any)— inserta en una posición.delete(start, end)— elimina un rango.reverse()— invierte el contenido del builder.length()ysetLength(n)— leer / truncar.toString()— produce laStringfinal.
También existe StringBuffer, que es idéntico pero seguro para hilos (todos sus métodos son synchronized). Casi nunca lo necesitarás; usa StringBuilder salvo que realmente compartas el builder entre hilos.
String.join — para colecciones
Cuando tienes una colección de cadenas y un separador, String.join es la opción más limpia:
String csv = String.join(",", "a", "b", "c"); // "a,b,c"
String csv2 = String.join(", ", List.of("a", "b", "c")); // "a, b, c"Para opciones de unión más avanzadas (collectors, inclusión condicional), consulta Collectors.joining de los streams más adelante en el libro.
Cuándo usar cada opción
Un árbol de decisión aproximado:
- Uno o dos fragmentos, legible de izquierda a derecha →
+. - Varios fragmentos con formato por tipo →
String.formatoformatted. - Literal de varias líneas → bloque de texto, opcionalmente con
.formatted. - Construir pieza a pieza en un bucle →
StringBuilder. - Unir una colección con un separador →
String.join.
Para concatenaciones pequeñas, los compiladores modernos y la JVM (con la concatenación de strings basada en invokedynamic introducida en Java 9) hacen que + sea muy rápido: el rendimiento no es razón para evitarlo en casos simples.
Demostración del caso con bucles
Qué sigue
Caracteres especiales y secuencias de escape en Java — qué hacen \n, \t, \" y los escapes Unicode.