Java, String, ‘+’, .concat() y eficiencia
29-02-2024
Trabajando en proyecto, @RubenZaGon, Francisco y yo, tuvimos la clásica duda de qué sería más óptimo para concatenar varios strings en cierta parte del código que actualmente lo hace mediante el operador +
.
Este operador está mal visto, porque es sabido como cultura general, que tiene un peor rendimiento que recurrir a las clases StringBuilder
o StringBuffer
, (recordatorio de que StringBuffer
es la versión thread-safe, ya que trabaja de forma síncrona), pero ¿qué hay del método .concat()
de la propia clase String
?
Como bien llegamos a razonar, un String
en Java es un objeto inmutable, un value object. Esto quiere decir que, cualquier operación realizada sobre un objeto instanciado de esta clase, no modifica el propio objeto sino que nos devuelve una nueva instancia con el valor del resultado.
¿Afecta entonces al rendimiento usar un método de esta misma clase, que en principio debería devolver igualmente un nuevo objeto String
?
Ambas formas de concatenar cadenas se comportan de forma similar pero tienen ligeras diferencias:
.concat()
instancia un nuevo objeto sólo si la cadena con la que se está concatenando tiene una longitud mayor a 0, mientras que el operador+
lo hará igualmente..concat()
lanza unNullPointerException
cuando se intenta concatenarnull
a unString
, mientras que el operador+
lo transforma y concatena elString
“null”.
Lo mismo ocurre si se intenta concatenar cualquier otro tipo de dato que no seaString
,.concat()
. Lo considerará una situación excepcional, mientras que+
simplemente llamará al método.toString()
del objeto en cuestión de forma implícita.
Esto es un ejemplo de como el comportamiento del operador +
, al ser más simplista, tiende a tener un mejor rendimiento que el método .concat()
, puesto que este último tiene en cuenta más situaciones en su definición.
Además, en lo personal, me parece más legible el operador +
que el método .concat()
. Aunque el nombre del método esté describiendo explícitamente la operación que se realiza, da la sensación de estar introduciendo ruido en forma de palabras en medio de las cadenas que estás intentando leer de forma continua.
¿Quiere decir esto que deberíamos usar siempre +
? Evidentemente no, como todo es cuestión de contexto.
StringBuilder
y StringBuffer
siguen teniendo un mejor rendimiento cuando se necesita concatenar una gran cantidad de cadenas, y aún así, si quisiéramos rizar el rizo y ser estrictos con el rendimiento, no sería recomendable realizar este tipo de operaciones de forma masiva sobre objetos inmutables. Aunque hoy en día es muy barato el coste de instanciar objetos en memoria, todo se acaba traduciendo en mayor número de llamadas al Garbage Collector de Java, lo que no deja de ser una penalización en el tiempo de ejecución.