Concatenando Strings en Java

Publicado el 4 de March de 2007 por Paco

Es un truco muy conocido y lo recuerdan en esta entrada de javaHispano.

Cuando se usa el operador “+” con dos instancias de String, el compilador, lo que hace es sustituir la operación por la creación de un StringBuffer.

En el ejemplo del artículo aparecen estos dos fragmentos de código:

// Caso ineficiente (pero típico)
long start = System.currentTimeMillis();
String str = "";
for(int i = 0; i < 10000; i++)
str += i;
System.out.println((System.currentTimeMillis() - start) / 1000.0d);

// Caso eficiente
start = System.currentTimeMillis();
StringBuffer strb = new StringBuffer();
for(int i = 0; i < 10000; i++)
strb.append( i );
System.out.println((System.currentTimeMillis() - start) / 1000.0d);

En el primer fragmento de código, el compilador sustituye el contenido del bucle con un código similar al siguiente:

for (int i=0; i<10000; i++){
    StringBuffer sb = new StringBuffer(str);
    sb.append(i);
    String straux = sb.toString();
    str = sb.toString();
}

A cada iteración se debe ubicar en memoria un nuevo objeto y ese objeto tiene un tamaño cada vez mayor.
La creación dinámica de memoria es una de las operaciones más costosas en Java (y en la mayoría de lenguajes que conozco) y la creación de 10000 instancias de StringBuffer hace que el mismo código resulte mucho más lento.

Ejecutando el código comparativo en mi portátil obtengo 3.277s para ejecutar el bucle con la versión ineficiente y 0.004s en la versión eficiente.

Podéis comprobarlo personalmente copiando y pegando este codigo:

public class Test{
        public static void main(String[] args){
                long start;
                String str;
                StringBuffer strb;

                // Usando el operador "+"
                str = "";
                start = System.currentTimeMillis();
                for(int i = 0; i < 10000; i++) str += i;
                System.out.println((System.currentTimeMillis() - start) / 1000.0d); 

                // Usando una instancia de StringBuffer y el método append()
                strb = new StringBuffer();
                start = System.currentTimeMillis();
                for(int i = 0; i < 10000; i++) strb.append(i);
                System.out.println((System.currentTimeMillis() - start) / 1000.0d); 

                // Reroducción de lo que hace el compilador en el caso 1
                str = "";
                start = System.currentTimeMillis();
                for (int i=0; i<10000; i++){
                        StringBuffer sbaux = new StringBuffer();
                        sbaux.append(str);
                        sbaux.append(i);
                        String straux = sbaux.toString();
                        str = straux;
                }
                System.out.println((System.currentTimeMillis() - start) / 1000.0d);
        }
}

Publicado bajo Java |

4 comentarios

  1. Gravatar del autor del comentario
    public class Ineficient
    {
    	public static void main (String[] args)
    	{
    		String str = "";
    		for (int i = 0; i < 20000; i++) str += i;
    	}
    }
    

    Promig de tres execucions: 41.342s.

    public class Eficient
    {
    	public static void main (String[] args)
    	{
    		StringBuffer strb = new StringBuffer ();
    		for (int i = 0; i < 20000; i++) strb.append (i);
    	}
    }
    

    Promig de tres execucions: 0.173s.

    #!/usr/bin/env ruby
    str = ""
    20000.times { |i| str += "#{i}" }
    

    Promig de tres execucions: 2.104s.

    #!/usr/bin/env ruby
    str = ""
    20000.times { |i| str.concat("#{i}") }
    

    Promig de tres execucions: 0.054s.

    (Comentari editat per tal de veure bé el codi ;-))

  2. Gravatar del autor del comentario

    Otia quin xurro… bé, ho deixaré a http://bulma.net/beowulf/misc/strings.txt

  3. Comentario de Tribe el Monday 5 March 2007 a las 17:02
    Gravatar del autor del comentario

    Vaya, qué sorpresa. Del orden de 250 veces más rápido en Java y 40 veces en Ruby según los resultados de Guillem, bestial.

    Por otra parte impresionante el resaltado de sintaxis en Kate de KDE 3.5.6 al abrir el fichero de texto de Guillem.

    Ah, muy interesantes estas entradas Paco sobre Java, a ver si te animas a poner más ahora que es(?) GPL, como decías en otra entrada :)

    Salud!

  4. Comentario de Enrique el Thursday 10 May 2007 a las 23:19
    Gravatar del autor del comentario

    Que bueno justo buscaba como concatenar un int a un string en ruby muchas gracias.


Deja un comentario

Por favor, ten en cuenta que: Los comentarios están moderados y la publicación del comentario podría demorarse hasta ser aprobaddo.

Publicidad

Más publicidad :-)

advising investment services best hyip monitoring rating best hyip program best investment firm best investment opportunity best mutual funds classics investment operator reminiscence stock wiley club estate investment real diversified investment essential of investment estate investment property real estate investment real trust extra income fixed income from investment profit uranium us fundamentals of investment gold investment high capital investments high income high profit fund raising high profit margin high yield investments highest financial returns highest fixed rate hyip invest hyip investment hyip monitoring hyip rating income opportunity investment an introduction investment casting investment club investment company investment land investment portfolio investment property investment putnam investment strategy new hyip offshore investment real estate investment club stock investment guide top mutual funds