Suponiendo las cadenas a y b:
a += b
a = a.concat(b)
Debajo del capó, ¿son lo mismo?
Aquí está concat descompilado como referencia. También me gustaría poder descompilar el +
operador para ver qué hace.
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
}
else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
java
string
concatenation
shsteimer
fuente
fuente
+
se pueda descompilar.StringBuffer
oStringBuilder
- (hilo inseguro por lo tanto más rápido, en su lugarRespuestas:
No, no del todo.
En primer lugar, hay una ligera diferencia en la semántica. Si
a
es asínull
,a.concat(b)
arroja unNullPointerException
peroa+=b
tratará el valor original dea
como si lo fueranull
. Además, elconcat()
método solo aceptaString
valores, mientras que el+
operador convertirá silenciosamente el argumento en una Cadena (utilizando eltoString()
método para objetos). Entonces, elconcat()
método es más estricto en lo que acepta.Para mirar debajo del capó, escriba una clase simple con
a += b;
Ahora desmonte con
javap -c
(incluido en Sun JDK). Debería ver una lista que incluye:Entonces,
a += b
es el equivalente deEl
concat
método debería ser más rápido. Sin embargo, con más cadenas, elStringBuilder
método gana, al menos en términos de rendimiento.El código fuente de
String
yStringBuilder
(y su clase base de paquete privado) está disponible en src.zip del Sun JDK. Puede ver que está creando una matriz de caracteres (redimensionando según sea necesario) y luego tirándola cuando cree la finalString
. En la práctica, la asignación de memoria es sorprendentemente rápida.Actualización: como señala Pawel Adamski, el rendimiento ha cambiado en HotSpot más reciente.
javac
todavía produce exactamente el mismo código, pero el compilador de bytecode hace trampa. Las pruebas simples fallan por completo porque se desecha todo el cuerpo del código. La sumaSystem.identityHashCode
(noString.hashCode
) muestra que elStringBuffer
código tiene una ligera ventaja. Sujeto a cambios cuando se lance la próxima actualización, o si usa una JVM diferente. De @lukaseder , una lista de intrínsecos de HotSpot JVM .fuente
javap -c
una clase compilada que lo usa. (. Oh, como en la respuesta Sólo tiene que interpretar el código de bytes de desmontaje, que no debería ser tan difícil.)StringBuilder
incluso cuando une dos cadenas. Si seString
incluyen métodos estáticos para concatenar hasta cuatro cadenas, o todas las cadenas de unString[]
código, podría agregar hasta cuatro cadenas con dos asignaciones de objetos (el resultadoString
y su respaldochar[]
, ninguno redundante), y cualquier número de cadenas con tres asignaciones ( elString[]
, el resultadoString
y el respaldochar[]
, siendo solo el primero redundante). Tal como está, el usoStringBuilder
requerirá en el mejor de los casos cuatro asignaciones, y requerirá copiar cada carácter dos veces.Niyaz es correcto, pero también vale la pena señalar que el compilador Java puede convertir el operador especial + en algo más eficiente. Java tiene una clase StringBuilder que representa una cadena mutable no segura para subprocesos. Al realizar un montón de concatenaciones de cadenas, el compilador de Java convierte silenciosamente
dentro
que para cadenas grandes es significativamente más eficiente. Hasta donde yo sé, esto no sucede cuando usas el método concat.
Sin embargo, el método concat es más eficiente cuando se concatena una cadena vacía en una cadena existente. En este caso, la JVM no necesita crear un nuevo objeto String y simplemente puede devolver el existente. Consulte la documentación de concat para confirmar esto.
Entonces, si está súper preocupado por la eficiencia, debe usar el método concat al concatenar cadenas posiblemente vacías y usar + de lo contrario. Sin embargo, la diferencia de rendimiento debería ser insignificante y probablemente nunca debería preocuparse por esto.
fuente
String
, como dices,concat
tiene una excepción cuando concatás un vacíoString
.Ejecuté una prueba similar a @marcio pero con el siguiente bucle en su lugar:
Solo por si acaso, también lo hice
StringBuilder.append()
. Cada prueba se ejecutó 10 veces, con 100k repeticiones para cada ejecución. Aquí están los resultados:StringBuilder
gana sin dudas. El resultado del tiempo de reloj fue 0 para la mayoría de las carreras, y el más largo tardó 16 ms.a += b
toma alrededor de 40000 ms (40 s) por cada ejecución.concat
solo requiere 10000 ms (10 s) por ejecución.No he descompilado la clase para ver los elementos internos o ejecutarlo a través del generador de perfiles todavía, pero sospecho que
a += b
pasa la mayor parte del tiempo creando nuevos objetosStringBuilder
y luego volviéndolos a convertirString
.fuente
+
se usa para dos cadenas, ¿hay algún caso en el que el usoStringBuilder
sea mejor de lo que seríaString.valueOf(s1).concat(s2)
? ¿Alguna idea de por qué los compiladores no usarían este último [o de lo contrario omitirían lavalueOf
llamada en casos dondes1
se sabe que no es nulo]?La mayoría de las respuestas aquí son de 2008. Parece que las cosas han cambiado con el tiempo. Mis últimos puntos de referencia realizados con JMH muestran que en Java 8
+
es aproximadamente dos veces más rápido queconcat
.Mi punto de referencia:
Resultados:
fuente
String
nunca incluyó una función estática para formar una cadena concatenando los elementos de aString[]
. Usar+
para concatenar 8 cadenas usando una función de este tipo requeriría construir y luego abandonarString[8]
, pero ese sería el único objeto que necesitaría construirse abandonado, mientras que usar aStringBuilder
requeriría construir y abandonar laStringBuilder
instancia y al menos unachar[]
tienda de respaldo.String.join()
métodos estáticos en Java 8, como envoltorios rápidos de sintaxis en toda lajava.util.StringJoiner
clase.+
cambiado el manejo de usar estas funciones?+
para usarlo) requeriría más de lo que los desarrolladores de Java están dispuestos a cambiar, lamentablemente.Tom tiene razón al describir exactamente lo que hace el operador +. Crea un temporal
StringBuilder
, agrega las partes y termina contoString()
.Sin embargo, todas las respuestas hasta ahora están ignorando los efectos de las optimizaciones de tiempo de ejecución de HotSpot. Específicamente, estas operaciones temporales se reconocen como un patrón común y se reemplazan con un código de máquina más eficiente en tiempo de ejecución.
@marcio: Has creado un micro-punto de referencia ; con las JVM modernas, esta no es una forma válida de codificar el perfil.
La razón por la que la optimización del tiempo de ejecución es importante es que muchas de estas diferencias en el código, incluso la creación de objetos, son completamente diferentes una vez que HotSpot se pone en marcha. La única forma de saberlo con certeza es perfilando su código in situ .
Finalmente, todos estos métodos son de hecho increíblemente rápidos. Este podría ser un caso de optimización prematura. Si tiene un código que concatena muchas cadenas, la forma de obtener la velocidad máxima probablemente no tenga nada que ver con los operadores que elija y, en cambio, el algoritmo que está utilizando.
fuente
¿Qué tal algunas pruebas simples? Usó el siguiente código:
"a + b"
versión ejecutada en 2500ms .a.concat(b)
ejecutado en 1200ms .Probado varias veces. La
concat()
ejecución de la versión tomó la mitad del tiempo en promedio.Este resultado me sorprendió porque el
concat()
método siempre crea una nueva cadena (devuelve un "new String(result)
". Es bien sabido que:¿Por qué el compilador no fue capaz de optimizar la creación de cadenas en el código "a + b", sabiendo que siempre resultó en la misma cadena? Podría evitar una nueva creación de cadena. Si no crees en la declaración anterior, prueba tu autoevaluación.
fuente
Básicamente, hay dos diferencias importantes entre + y el
concat
método.Si está utilizando el método concat , entonces solo podrá concatenar cadenas, mientras que en el caso del operador + , también puede concatenar la cadena con cualquier tipo de datos.
Por ejemplo:
En este caso, la salida debería ser 10Hola .
En el caso anterior, debe proporcionar dos cadenas obligatorias.
La segunda y principal diferencia entre + y concat es que:
Caso 1: suponga que concaté las mismas cadenas con el operador concat de esta manera
En este caso, el número total de objetos creados en el grupo es 7 como este:
Caso 2:
Ahora voy a concatenar las mismas cadenas a través del operador +
En el caso anterior, el número total de objetos creados son solo 5.
En realidad, cuando concatenamos las cadenas a través del operador + , mantiene una clase StringBuffer para realizar la misma tarea de la siguiente manera:
De esta manera creará solo cinco objetos.
Entonces, estas son las diferencias básicas entre + y el método concat . Disfruta :)
fuente
String s="I"+"am"+"good"+"boy"; String s2 = "go".concat("od"); System.out.println(s2 == s2.intern());
impresionestrue
, lo que significa que"good"
no estaba en el grupo de cadenas antes de llamarintern()
En aras de la exhaustividad, quería agregar que la definición del operador '+' se puede encontrar en el JLS SE8 15.18.1 :
Sobre la implementación, JLS dice lo siguiente:
Entonces, a juzgar por 'un compilador de Java puede usar la clase StringBuffer o una técnica similar para reducir', diferentes compiladores podrían producir diferentes códigos de bytes.
fuente
El operador + puede trabajar entre una cadena y un valor de tipo de datos string, char, integer, double o float. Simplemente convierte el valor a su representación de cadena antes de la concatenación.
El operador concat solo se puede hacer con y con cadenas. Comprueba la compatibilidad del tipo de datos y arroja un error, si no coinciden.
Excepto esto, el código que proporcionó hace lo mismo.
fuente
No lo creo.
a.concat(b)
está implementado en String y creo que la implementación no cambió mucho desde las primeras máquinas java. La+
implementación de la operación depende de la versión y el compilador de Java. Actualmente+
se implementa utilizandoStringBuffer
para hacer la operación lo más rápido posible. Quizás en el futuro esto cambie. En versiones anteriores de Java, la+
operación en Strings era mucho más lenta ya que producía resultados intermedios.Supongo que
+=
se implementa usando+
y optimizado de manera similar.fuente
Cuando se usa +, la velocidad disminuye a medida que aumenta la longitud de la cadena, pero cuando se usa concat, la velocidad es más estable, y la mejor opción es usar la clase StringBuilder que tiene velocidad estable para hacerlo.
Supongo que puedes entender por qué. Pero la mejor manera de crear cadenas largas es usar StringBuilder () y append (), ya que cualquiera de las dos velocidades será inaceptable.
fuente