metodo - concatenar en java eclipse
¿Cuál es la diferencia al concatenar una cadena como una variable con un personaje frente a una cadena diferente? (7)
Basándome en la respuesta aceptada aquí, espero poder comenzar a ver qué hay debajo del capó.
Echemos un vistazo al código de bytes generado al concatenar una cadena con un carácter:
String str1 = "a" + "test";
String str2 = ''a'' + "test";
0: ldc #2 // String atest
2: astore_1
3: ldc #2 // String atest
5: astore_2
Como puede ver, no hay diferencia, el compilador lo convertirá al mismo bytecode.
Ahora echemos un vistazo al código de bytes generado cuando concatene un carácter a una variable de cadena.
String str1 = "a" + str3; //str3 is a String
String str2 = ''a'' + str3;
7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
10: ldc #5 // String a
12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: aload_1
16: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_2
23: new #3 // class java/lang/StringBuilder
26: dup
27: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
30: bipush 97
32: invokevirtual #8 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
35: aload_1
36: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
39: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
Como puedes ver, hay una pequeña diferencia.
10: ldc #5 // String a
ldc
un #index constante de un grupo constante (String, int o float) en la pila.
Por lo tanto, si está concatenando directamente con una variable, concatenar un carácter generará menos bytecode, eso es lo que está debajo del capó .
Ahora, para el problema de rendimiento, esto no representará ninguna diferencia significativa de rendimiento, ya que el compilador JIT optimiza la mayoría de los objetos temporales, a menos que haya especificado al ejecutar su programa para deshabilitar el compilador JIT usando -Djava.compiler=NONE
.
Cuando veo algo (pseudo 1-liner) como este:
str1 + "a" + str2
¿Es mucho peor (o mejor / igual) que lo siguiente (pseudo 1-liner)?
str1 + ''a'' + str2
Actualización: Mejor ejemplo (por @QPaysTaxes) para reducir la confusión con respecto a mi ejemplo original.
Lo que intenté: varias cosas durante los últimos 10 años en la programación de Java, pero nunca logré ver realmente qué hay debajo del capó. Por ejemplo, asumiría que el segundo es ligeramente "más rápido / mejor" porque no hay ningún objeto de cadena creado para El slash-sign y / o el recolector de basura de Java tienen que manejar menos. Una vez me preparé para los Certificados de Java y podría haber sido capaz de argumentar mejor en ese tiempo, pero parece que incluso así es mi asunto cotidiano, la "teoría" sobre Java debe mantenerse actualizada también ... Lo sé sin ninguna Una mejor explicación que mi suposición de que se indexOf(''c'')
usar indexOf(''c'')
lugar de indexOf("C")
y me pregunté si lo mismo cuenta para la concatenación de cadenas.
También busqué un poco en Google, pero como mi título podría implicar, no soy muy bueno para describir lo que estoy buscando sin un ejemplo. Lo siento por esto y la posibilidad de que esta desventaja haya producido un duplicado.
Qué intentaré: en función de la respuesta aceptada aquí Concatenación de cadenas: operador concat () vs "+" espero poder comenzar para ver qué hay debajo del capó y algún día poder discutir / responder preguntas de este tipo que profundicen .
Esto es lo que está debajo del capó: String str = s1 + "/";
Básicamente crea 2 nuevos objetos String separados ( str
y new String("/"))
.
Esto no es un problema para el software pequeño, pero piénselo en memoria si tuviera que crear 2 objetos String (tenga en cuenta que: los objetos reservan 1 entrada en la Pila más el contenido guardado en el Heap) para n> 500.000 entradas de base de datos.
El uso de comillas simples, como String str = s1 + ''/''
, resultará en otro proceso completamente. ''/''
representa el valor de la representación numérica de caracteres ASCii de cualquier carácter único que se escriba entre las comillas. Esta operación tiene un tiempo de ejecución constante ( O (1) ) (piense en el acceso a la matriz instantánea) y, naturalmente, será más rápida que crear y hacer referencia a objetos.
Como mucha gente ya ha sugerido, usar un objeto StringBuilder
para la concatenación de cadenas es mucho más fácil en la memoria que crear cadenas con el operador +.
Mirar el código fuente a menudo ayuda a entender lo que está sucediendo.
String s = s1 + s2
Ejecutará:
String s = new StringBuilder(s1).append(s2).toString();
Ahora mire el código fuente para anexar (char) y anexar (cadena) de la clase StringBuilder
:
Verá que el anexo (cadena) realiza más comprobaciones para ver si la cadena es nula o está vacía. Sin embargo, probablemente no notará ninguna diferencia.
No estoy seguro de que alguna de las opciones sea mejor en términos de rendimiento, pero puedo pensar en otro tema a considerar, que preferiría el primer fragmento.
El compilador puede protegerlo mejor contra errores tipográficos si agrega primitivas en lugar de la representación de cadena de esas primitivas.
Considerar:
String plus10 = "plus" + 10;
Si escribes por error
String plus10 = "plus" + 1O;
El compilador te dará un error.
Si, por otro lado, escribes
String plus10 = "plus" + "1O";
El compilador no tendrá ningún problema con eso.
Lo mismo vale para añadir caracteres.
String plus = "x" + ''++'' + "y";
no compilará mientras
String plus = "x" + "++" + "y";
Pasará la compilación.
Por supuesto, sería mejor usar constantes y no valores codificados (y añadirlos a un StringBuilder
lugar de usar concatenación de String
), pero incluso para las constantes, preferiría los tipos primitivos en lugar de cadenas, ya que le brindan un nivel más de protección. contra errores.
No hay ninguna diferencia significativa en el rendimiento en realidad. Un promedio tomará el mismo tiempo para hacer la concatenación de cadenas.
Sin embargo, el compilador Java interno reemplaza el operador +
con StringBuilder
en el momento de la compilación.
Así que cuando se usa el operador +
con char, el compilador lo convertirá en un StringBuilder
internamente y usará .append(char)
. Lo mismo ocurrirá con una cadena, con la diferencia de que usará .append(String)
.
Y como mencioné anteriormente, no hay diferencia en un promedio. La prueba simple mostrará que la diferencia de tiempo es cercana a 0. Así que esto es realmente cuestión de legibilidad. Y desde la perspectiva de la legibilidad, si está concentrando cadenas, es mejor mantener el mismo tipo y usar la cadena incluso para caracteres individuales, en lugar de caracteres.
Prefiero usar "a"
lugar de ''a''
para asegurarme de que el resultado sea una String
.
Considera esto:
public static void main(String... args) {
String s = "foo";
int i = 1;
Object arg = s + ''/'' + i;
log(arg);
}
private static void log(Object... args) {
MessageFormat format = new MessageFormat("bar {0}");
String message = format.format(args);
System.out.println(message); // or write to a log or something
}
Suponga que decide que ya no necesita s
en el mensaje y cambie la tercera línea en el método main
para:
Object arg = ''/'' + i;
Entonces arg
contendrá solo un número, porque char + int
no concatena, sino que agrega los valores.
Si construyes un nombre de archivo seguro que lo usarás después. Eso en la mayoría de los casos implica el acceso a un medio físico que es una magnitud más lenta que cualquier otra cosa que pueda hacer mal al concatenar sus Cuerdas. Entonces, haga lo que sea maintable y no se preocupe por el rendimiento en este caso particular.
Mi consejo al crear nombres de archivos es usar la clase de File
o la Path
que automáticamente se asegurará de obtener los separadores de ruta correctos.
EDITAR: Como señala en su comentario, su pregunta es sobre el caso general. Solo mira la fuente. StringBuilder.append(String)
termina haciendo un System.arraycopy()
en String.getChars()
mientras que StringBuilder.append(char)
copia directamente un solo carácter. Entonces, en teoría, StringBuilder.append(char)
será más rápido.
Sin embargo, tendrías que comparar esto para ver si hay alguna diferencia en la práctica.