2012-01-06 18 views
23

Para la concatenación de cadenas podemos usar el operador de concat() o concat (+).operador de concatenación (+) frente concat()

He intentado la siguiente prueba de rendimiento y encontré concat() es más rápido y una manera eficiente de memoria para la concatenación de cadenas.

cadena de comparación concatenación de 100.000 veces:

String str = null; 

//------------Using Concatenation operator------------- 
long time1 = System.currentTimeMillis(); 
long freeMemory1 = Runtime.getRuntime().freeMemory(); 

for(int i=0; i<100000; i++){ 
    str = "Hi"; 
    str = str+" Bye"; 
} 
long time2 = System.currentTimeMillis(); 
long freeMemory2 = Runtime.getRuntime().freeMemory(); 

long timetaken1 = time2-time1; 
long memoryTaken1 = freeMemory1 - freeMemory2; 
System.out.println("Concat operator :" + "Time taken =" + timetaken1 + 
        " Memory Consumed =" + memoryTaken1); 

//------------Using Concat method------------- 
long time3 = System.currentTimeMillis(); 
long freeMemory3 = Runtime.getRuntime().freeMemory(); 
for(int j=0; j<100000; j++){ 
    str = "Hi"; 
    str = str.concat(" Bye"); 
} 
long time4 = System.currentTimeMillis(); 
long freeMemory4 = Runtime.getRuntime().freeMemory(); 
long timetaken2 = time4-time3; 
long memoryTaken2 = freeMemory3 - freeMemory4; 
System.out.println("Concat method :" + "Time taken =" + timetaken2 + 
        " Memory Consumed =" + memoryTaken2); 

Resultado

Concat operator: Time taken = 31; Memory Consumed = 2259096 
Concat method : Time taken = 16; Memory Consumed = 299592 

Si concat() es más rápido que el operador entonces cuando debemos utilizar operador de concatenación (+)?

+1

Lea: http://stackoverflow.com/questions/693597/is-there-a-difference-between-string-concat-and-the-operator-in-java y http://stackoverflow.com/questions/47605/java-string-concatenation –

+0

Lo único que se ve diferente es que cuando la cadena que está agregando tiene longitud cero, simplemente le devuelve el original en lugar de crear una nueva Cadena. El operador + puede ser un poco caro ... si está haciendo cientos o miles de operaciones de creación de cadenas, mire en StringBuffer.append(). Es común ver un método construir un StringBuffer y luego devolver o usar elBuffer.toString() al final. –

+0

@PankajKumar bien, es probable que desee StringBuilder en lugar de StringBuffer – ymajoros

Respuesta

30

El método concat siempre produce una nueva cadena con el resultado de la concatenación.

El operador además está respaldado por la creación de StringBuilder, añadiendo todos los valores de cadena que necesita y más toString() de llamada en él.

lo tanto, si usted necesita para concatenar dos valores, concat() será mejor elección. Si necesita concatenar 100 valores, debe usar el operador más o usar StringBuilder explícitamente (por ejemplo, en caso de agregar en un ciclo).

+4

Su último comentario solo es verdadero para todas las concatenaciones de cadenas que están en la ** misma expresión **. Entonces, un 'StringBuilder' se usa para' x = a + b + c' (asumiendo que todos son 'String's), pero dos' StringBuilder's se usan para 'x = a + b; x + = c; '. –

+1

Como una adición a la respuesta de Artem, [este] (http://www.znetdevelopment.com/blogs/2009/04/06/java-string-concatenation/) enlace, que parece ser una publicación de blog desde atrás en ' 09 con respecto a esta pregunta específica. Con suerte, el enlace dará un poco más de contexto para las respuestas y comentarios que Artem y TJ han proporcionado, aunque no puedo verificar las afirmaciones hechas en el artículo ya que no soy ningún experto en Java ... – blahman

+2

Don ' t quiere decir 'explícitamente use StringBuilder' –

-2

En realidad, los dos son lo mismo. Si ve el código de concat(String paramString), devolverá un nuevo objeto de cadena, y en el operador (+) también generará un nuevo objeto de cadena.

Si no desea crear un objeto nuevo, utilice el generador de cadenas para concatenar dos cadenas.

+0

En cuanto a (+) no es cierto en su mayoría – dantuch

-1

En general, es una mala práctica concatenar cadenas con + y con concat(). Si desea crear una cadena use StringBuilder en su lugar.

+0

Esto obviamente es una respuesta incorrecta. Hay muchos casos en los que deberíamos usar + o concat() en lugar de StringBuilder/StringBuffer. –

+0

El caso que se muestra en la pregunta es la concatenación de cadena en un bucle, en ese caso creo que StringBuilder es la mejor manera de hacerlo, no solo en Java. – Felype

3

Creo que el 'estilo' de la concatenación marcará la diferencia.

Para concat(), internamente crea un nuevo búfer de matriz char, y devuelve una nueva cadena basada en esa matriz de caracteres.

Para el operador +, el compilador de hecho traducirlo al usar StringBuffer/StringBuilder.

Por lo tanto, si usted está concatenando dos cadenas, concat() es sin duda una mejor opción debido a que el número de objetos creados es sólo el cadenaresult (y el char buffer utilizado en el interior), mientras que el uso del operador + será traducido a :

result = strA + strB; 
-- translate to --> 
result = new StringBuilder(strA).append(strB).toString(); 

Se crea una instancia adicional de StringBuilder.

Sin embargo, si concatena, por ejemplo, cinco cadenas seguidas, cada concat() creará un nuevo objeto String. Al usar el operador +, el compilador traducirá la instrucción a un StringBuilder con múltiples operaciones de adición.Definitivamente está ahorrando una gran cantidad de instancia de objeto temporal innecesaria:

result = strA + strB + strC + strD + strE; 
-- translate to --> 
result = new StringBuilder(strA).append(strB).append(strC).append(strD).append(strE).toString(); 
+0

El punto de equilibrio es aproximadamente de cuatro cuerdas; la eficiencia relativa de '(String.valueOf (strA) .concat (strB)). concat (String.valueOf (strC) .concat (strD))' en comparación con el uso de un generador de cadenas es más o menos un lanzamiento. Para un máximo de ocho cadenas, la concatenación puede ser más lenta, pero nunca tan grande, y es probable que sea más rápida en los casos en que importaría (terminará copiando cada carácter exactamente tres veces; 'StringBuilder' copiará cada carácter dos veces si nunca debe expandirse, pero si las cadenas son grandes, es probable que se requiera una expansión). – supercat

0

Puede siempre uso + si sólo utilizar> = Java 1.5 y hacer no declarar la cadena de base (que desea concatenar) fuera del circuito. En Java 1.5, se crea new StringBuilder y se trabaja hasta que se completa la cadena. Esa es la forma más rápida.

De todas formas, si se encuentra en un bucle (y concatenando cadenas con +), cada iteración del ciclo crea un new StringBuilder; esa no es la mejor idea. Entonces aquí es donde deberías forzar el uso de las clases StringBuilder o StringBuffer (thread safe).

En general, este enlace claramente responde a su pregunta, y le da un conocimiento completo:

http://littletutorials.com/2008/07/16/stringbuffer-vs-stringbuilder-performance-comparison/

0

Aunque el operador y el método están dando el mismo resultado, la forma en que trabajan internamente difiere.

El método concat() que simplemente concatena str1 con str2 y genera una cadena, es más eficiente para un pequeño número de concatenaciones.

Pero con el operador de concatenación '+', str1+=str2; se interpretará como str1 = new StringBuilder().append(str1).append(str2).toString();

Puede usar el método concat cuando se utiliza un número menor de cadenas para concatenar. Pero el método StringBuilder sería rápido en términos de rendimiento si usa una gran cantidad de cadenas.

+0

Construir un generador de cadenas y usarlo repetidamente es bueno para el rendimiento, pero crear un generador de cadenas, usarlo para unir menos de cuatro cadenas y luego abandonarlo es contraproducente. Desafortunadamente, el compilador a menudo usa y abandona los constructores de cadenas después de usarlos para unir dos cadenas. – supercat

7

Su prueba debe ejecutarse durante al menos 2 segundos con cada ciclo en un método diferente para que tenga sentido. Las pruebas cortas pueden ser difíciles de reproducir y comparar. Según su tiempo, parece que está usando Windows (es decir, porque sus tiempos son 16 y 31 ms;) en su lugar, pruebe System.nanoTime(). Cuando su ciclo itera más de 10 000 veces, se compila todo el método. Esto significa que su método posterior ya está compilado cuando se inicia.

En respuesta a su pregunta, concat es marginalmente más rápido al agregar dos cadenas. Sin embargo, viene con un tipeo y una sobrecarga conceptual que probablemente sea mucho mayor que la CPU que guardas. Incluso en función de sus pruebas, que se repiten 100.000 veces, ahorra menos de 15 ms, y sin embargo le costó mucho, mucho más que eso en su tiempo (que probablemente valdrá más). Podría encontrar en una versión futura de la JVM, la la diferencia se optimiza siempre y la complejidad de su código aún está allí.


EDIT: No noté que el resultado de la memoria era sospechoso.

String str = null; 

//------------Using Concatenation operator------------- 
long time1 = System.currentTimeMillis(); 
long freeMemory1 = Runtime.getRuntime().freeMemory(); 
for (int i = 0; i < 10000; i++) { 
    str = "Hi"; 
    str = str + " Bye"; 
} 
long time2 = System.currentTimeMillis(); 
long freeMemory2 = Runtime.getRuntime().freeMemory(); 

long timetaken1 = time2 - time1; 
long memoryTaken1 = freeMemory1 - freeMemory2; 
System.out.println("Concat operator :" + "Time taken =" + timetaken1 + " Memory Consumed= " + memoryTaken1); 

str = null; 
//------------Using Concat method------------- 
long time3 = System.currentTimeMillis(); 
long freeMemory3 = Runtime.getRuntime().freeMemory(); 
for (int j = 0; j < 10000; j++) { 
    str = "Hi"; 
    str = str.concat(" Bye"); 

} 
long time4 = System.currentTimeMillis(); 
long freeMemory4 = Runtime.getRuntime().freeMemory(); 

long timetaken2 = time4 - time3; 
long memoryTaken2 = freeMemory3 - freeMemory4; 
System.out.println("Concat method :" + "Time taken =" + timetaken2 + " Memory Consumed= " + memoryTaken2); 

grabados cuando se ejecuta con -XX:-UseTLAB -mx1g

Concat operator :Time taken =12 Memory Consumed= 1291456 
Concat method :Time taken =7 Memory Consumed= 560000 

haciendo que la relación de uso de la memoria de aproximadamente 2: 1. En la pregunta original, el resultado varía cada vez que lo ejecuta, a veces parece que el .concat() usa más.

+0

"sin embargo, le costó mucho, mucho más que eso en su tiempo (que probablemente valdrá más)" ¿aquí el costo significa tipear y gastos generales conceptuales? Pero si ignoramos el beneficio de 15 ms, se puede argumentar que el uso de la memoria es 1/10th –

+0

@Naroji No puedo ver cómo la memoria es 1/10a, 15ms es el tiempo que toma presionar una tecla y es realmente trivial en términos de tiempo de desarrollo. –

+0

memoria consumida es 1/10th, como se menciona en la pregunta también. Operador Concat: Tiempo tomado = 31 Memoria consumida = "2,259,096" Método Concat: Tiempo tomado = 16 Memoria consumida = "299,592" –

9

De hecho s1 + s2 y s1.concat (s2) son muy diferentes.

s1 + s2 es convertido por javac en

(new StringBuilder(String.valueOf(s1)).append(s2).toString(); 

Se puede ver si descompilar .class. Esta construcción no es muy eficiente; implica hasta tres nuevas asignaciones de char [] y tres operaciones de copia de char [].

s1.concat (s2) es siempre una nueva char [] + operación de una copia, ver String.java

public String concat(String str) { 
    int otherLen = str.length(); 
    if (otherLen == 0) { 
     return this; 
    } 
    char buf[] = new char[count + otherLen]; 
    getChars(0, count, buf, 0); 
    str.getChars(0, otherLen, buf, count); 
    return new String(0, count + otherLen, buf); 
} 

Tenga en cuenta que la nueva cadena (int, int, char []) es un paquete de private String constructor. Utiliza char buf [] directamente, sin la copia habitual para garantizar la invisibilidad buf para la inmutabilidad String.

+0

Me pregunto por qué javac usa 'StringBuilder' incluso cuando combina menos de cuatro cadenas? Creo que 'String.valueOf (strA) .concat (strB) .concat (strC)' generaría código que era más compacto y, para cada combinación de longitudes de cadena, más rápido que 'strA + strB + strC' en realidad genera, a menos que JITter reemplace el código que llama a 'StringBuilder' con algo más eficiente. – supercat

Cuestiones relacionadas