2010-12-01 21 views
9

He estado leyendo el código producido por otros desarrolladores en mi equipo, parecen favorecer el uso de += para la concatenación de cadenas, mientras que prefiero usar .concat(), ya que es más fácil de leer.¿Es + = más eficiente que concat?

Estoy tratando de preparar un argumento sobre por qué es mejor usar .concat(), y me pregunto, ¿hay alguna diferencia en la eficiencia entre los dos?

¿Qué opción "debería" tomar?

public class Stuff { 

    public static void main(String[] args) { 

     String hello = "hello "; 
     hello += "world"; 
     System.out.println(hello); 

     String helloConcat = "hello ".concat("world"); 
     System.out.println(helloConcat); 
    } 
} 
+2

mira esto http://stackoverflow.com/questions/47605/java-string-concatenation –

Respuesta

6

Desde cadena es inmutable en Java, cuando se hace una +, += o concat(String), se genera una nueva cadena . Cuanto más grande sea la cadena, más tardará; hay más para copiar y se produce más basura.

Los compiladores de Java de hoy optimizan la concatenación de cadenas para que sea óptima, p.

System.out.println("x:"+x+" y:"+y); 

compilador genera a:

System.out.println((new StringBuilder()).append("x:").append(x).append(" y:").append(y).toString()); 

Mi consejo es escribir código que es más fácil de mantener y leer.

Este enlace muestra el rendimiento de StringBuilder vs StringBuffer vs String.concat - done right

10

No debería importar. Los compiladores de Java de hoy en día, JVM y JIT optimizarán su código de tal manera que las diferencias sean mínimas. Debes esforzarte para escribir código que sea más legible y mantenible para ti.

+0

¿Qué dirías en el caso de los procesadores móviles o donde los recursos son bajos, aún estos mínimo no importaría? – Pratik

+0

@Pratik: esos son casos en los que la optimización sí importa. La pregunta de OP no indicó que se necesitan micro optimizaciones. Por supuesto, debes tener cuidado con lo que estás haciendo en función de tu entorno. Si quisiera escribir un sistema operativo, no lo haría en un lenguaje dinámico lento si desea que sea muy rápido. – darioo

+0

No estoy seguro de qué optimización estás pensando aquí. –

5

Estoy de acuerdo con @darioo y la mayoría de las otras respuestas. Siempre ponga la legibilidad (y mantenibilidad) primero. (Un compilador JIT moderno no debería tener problemas con casos simples como estos.)

Sin embargo, aquí está el bytecode correspondiente a su programa. (Tenga en cuenta que los += enfoque da como resultado un StringBuilder que generalmente es el método preferido en la construcción de cadenas.)

// String hello = "hello"; 
0: ldC#2; //String hello 
2: astore_1 

// hello += "world"; 
3: new #3; //class java/lang/StringBuilder 
6: dup 
7: invokespecial #4; //Method StringBuilder."<init>" 
10: aload_1 
11: invokevirtual #5; //Method StringBuilder.append 
14: ldC#6; //String world 
16: invokevirtual #5; //Method StringBuilder.append 
19: invokevirtual #7; //Method StringBuilder.toString 

// System.out.println(hello); 
22: astore_1 
23: getstatiC#8; //Field System.out 
26: aload_1 
27: invokevirtual #9; //Method PrintStream.println 

// String helloConcat = "hello ".concat("world"); 
30: ldC#2; //String hello 
32: ldC#6; //String world 
34: invokevirtual #10; //Method String.concat 
37: astore_2 

// System.out.println(helloConcat); 
38: getstatiC#8; //Field System.out 
41: aload_2 
42: invokevirtual #9; //Method PrintStream.println 

45: return 
3

En términos de facilidad de lectura, creo que estás muy equivocado. + gana más de .concat(). Si está utilizando +=, es posible que desee pensar en StringBuilder.append manteniendo el mismo StringBuilder para el bucle.

En términos de rendimiento concat es mejor que +. siempre y cuando solo uses uno o tal vez dos. En el caso de concat, terminará creando un objeto String con un tamaño correcto char[]. Es lo más óptimo que puedes obtener.

Para + javac genera el código que construye un StringBuilder para hacer el anexar y luego lo convierte en String. De 1.5 se crea:

  • A (residuos) StringBuilder
  • inicial char[] para StringBuilder (residuos)
  • Si resulta secuencia es demasiado largo, un segundo más grande char[] (residuos)
  • El resultado String.
  • String 's char[].

Sin embargo, rara vez se ve concat porque es más difícil de leer. El rendimiento es casi seguro que será una gota en el océano en comparación con lo que está sucediendo (sugerencia: pruebe el reverso de un sobre antes de optimizarlo).

1

Debe hacer lo que encuentre más corto y claro para usted.

Sin embargo, para su interés.

String hello = "hello " + "world"; 

Es el más rápido ya que la compilación combinó las dos Cadenas en una.

Este es el más rápido para dos cadenas ya que evita la creación de StringBuilder.

String helloConcat = "hello ".concat(world); 

Sin embargo, si usted tiene más de dos cadenas utilizando StringBuilder, implícita o explícitamente, es más rápido.

En resumen, usaría + a menos que lo tenga en un bucle en cuyo caso podría usar StringBuilder explícitamente para mejorar el rendimiento.

0

He encontrado que esto artical y realizado esta prueba:

public static void main(String[] args) { 
     String s1 = generateString(); 
     String s2 = generateString(); 
     String s3 = generateString(); 
     String s4 = generateString(); 
     String s5 = generateString(); 
     String s6 = generateString(); 

     long e = System.currentTimeMillis(); 
     for(int i=0;i<10000000;i++){ 
     //StringBuilder > concat> plus >StringBuffer >plusEqual(">"means faster than) 
      //concatPlus(s1 , s2 , s3 , s4 , s5 , s6);//4204ms 
      //concatBuilder(s1 , s2 , s3 , s4 , s5 , s6);//2562ms 
      //concatBuffer(s1 , s2 , s3 , s4 , s5 , s6);//4610ms 
      //concatPlusEqual(s1 , s2 , s3 , s4 , s5 , s6);//9843ms 
      //concatConcat(s1 , s2 , s3 , s4 , s5 , s6);//3036ms 
     } 
     System.out.println(System.currentTimeMillis()-e);   
    } 

public static String concatPlusEqual(String s1, String s2, String s3, String s4, 
     String s5, String s6) { 
     String result = ""; 
     result += s1; 
     result += s2; 
     result += s3; 
     result += s4; 
     result += s5; 
     result += s6; 
     return result; 
} 

    public static String concatConcat(String s1, String s2, String s3, String s4, 
      String s5, String s6) { 
     String result = new String(); 
     result.concat(s1); 
     result.concat(s2); 
     result.concat(s3); 
     result.concat(s4); 
     result.concat(s5); 
     result.concat(s6); 
     return result; 
    } 


    public static String concatBuffer(String s1, String s2, String s3, String s4, 
      String s5, String s6) { 
     return new StringBuffer(s1.length() + s2.length() + s3.length() 
       + s4.length() + s5.length() + s6.length()).append(s1) 
       .append(s2).append(s3).append(s4).append(s5).append(s6) 
       .toString(); 
    } 

    public static String concatBuilder(String s1, String s2, String s3, String s4, 
      String s5, String s6) { 
     return new StringBuilder(s1.length() + s2.length() + s3.length() 
       + s4.length() + s5.length() + s6.length()).append(s1) 
       .append(s2).append(s3).append(s4).append(s5).append(s6) 
       .toString(); 
    } 

    public static String concatPlus(String s1,String s2,String s3,String s4,String s5,String s6) { 
     return s1 + s2 + s3 + s4 + s5 + s6; 
    } 
public static String generateString() 
    { 
     Random rng = new Random(); 
     int length = 10; 
     String characters ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
     char[] text = new char[length]; 
     for (int i = 0; i < length; i++) 
     { 
      text[i] = characters.charAt(rng.nextInt(characters.length())); 
     } 
     return new String(text); 
    } 

Parece que StringBuilder es más rápida y += es más lento. ¡Solo como referencia!

1

de concatenación es definitivamente una opción más rápida para concatenar dos cadenas, no sé qué javac utiliza internamente

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

en lugar de

s1.concat(s2) 

para s1 = s2 +. Ver mi respuesta a una pregunta similar concatenation operator (+) vs concat()

Cuestiones relacionadas