Otra pregunta: ¿por qué usa un SB solo para una iteración del ciclo? ¿Hay otra iteración interna? SB no vale la pena si simplemente quieres hacer A + B + C + D (el compilador de Java usará internamente un SB). Es útil si desea agregar condicionalmente partes de cadenas, pero de lo contrario ... simplemente use "+".
helios
Respuestas:
135
Una opción es utilizar el método de eliminación de la siguiente manera:
StringBuffer sb =newStringBuffer();for(int n =0; n <10; n++){
sb.append("a");// This will clear the buffer
sb.delete(0, sb.length());}
Otra opción (limpiador de bits) usa setLength (int len) :
Algo un poco menos basura sería simplemente declarar el StringBuffer dentro del bucle.
Mark Elliot
11
Ah, creo que sb.setLength (0); es más limpio y eficiente que declararlo dentro del ciclo. Su solución va en contra del beneficio de rendimiento de usar StringBuffer ...
Jon
6
Creo que el beneficio de rendimiento proviene de la mutabilidad de la cadena, no de guardar la instanciación. aquí hay una prueba rápida de iteraciones 1e8: bucle interno (2.97s): ideone.com/uyyTL14w , bucle externo (2.87s): ideone.com/F9lgsIxh
Mark Elliot
6
Hablando de rendimiento: a menos que se acceda a su código en un escenario de subprocesos múltiples, debe usar StringBuilder en lugar de StringBuffer; consulte javadoc: "Siempre que sea posible, se recomienda que esta clase se use en lugar de StringBuffer, ya que será más rápido en la mayoría de las implementaciones ".
Rahel Lüthy
4
El único beneficio de crear el SB en el exterior es no perder su carácter interno (potencialmente largo). Si en el primer iterador creció lo suficiente, el segundo ciclo no necesitará cambiar el tamaño de ningún carácter []. Pero para obtener la ventaja, el "método claro" tendrá que preservar el tamaño de la matriz interna. setLength hace eso, pero también establece en \ u0000 todos los caracteres no utilizados en el SB, por lo que tiene menos rendimiento que simplemente crear un nuevo SB con una buena capacidad inicial. Declarar dentro del bucle es mejor.
helios
48
La forma más sencilla de reutilizar StringBufferes utilizar el métodosetLength()
sb.setLength(0);// It will just discard the previous data, which will be garbage collected later.
O usar:
sb.delete(0, sb.length());// A bit slower as it is used to delete sub sequence.
NOTA
Evite declarar objetos StringBufferu StringBuilderobjetos dentro del ciclo, de lo contrario, creará nuevos objetos con cada iteración. La creación de objetos requiere recursos del sistema, espacio y también lleva tiempo. Por lo tanto, a largo plazo, evite declararlos dentro de un bucle si es posible.
Sugiero crear uno nuevo StringBuffer(o incluso mejor StringBuilder) para cada iteración. La diferencia de rendimiento es realmente insignificante, pero su código será más corto y sencillo.
Si tiene alguna evidencia de dicha diferencia de rendimiento, compártala. (También me alegrará ver estadísticas de dónde se usa principalmente Java y bajo qué definición de "principalmente".)
Eli Acherkan
1
Es bien sabido que la asignación (nueva palabra clave en Java) es más cara que simplemente cambiar algunos campos del mismo objeto. Para "la mayoría", que podría reemplazar con altamente, hay más de 1.500 millones de dispositivos Android, todos usando Java.
Louis CAD
1
Estoy de acuerdo en que en algunos casos, la legibilidad del código es más importante que el rendimiento, pero en este caso, ¡es solo una línea de código! Y puede ejecutar una evaluación comparativa que le demostrará que la asignación y la creación de objetos, además de la recolección de basura, es más costosa que no hacerlo en absoluto. Como estamos en un bucle, es más que relevante.
Louis CAD
1
También suscribí la opinión de Knuth, pero su punto de vista no siempre es cierto. Agregar solo una línea para potencialmente ganar ciclos de CPU y memoria no es nada malo. Estás tomando la idea demasiado en serio. Tenga en cuenta que un bucle generalmente se repite muchas veces. Un bucle se puede repetir miles de veces, lo que puede consumir preciosos megabytes en un dispositivo móvil (y también en un servidor o computadora) si no se optimiza con cuidado.
Louis CAD
1
Creo que ambos expresamos nuestros puntos de vista con suficiente claridad y creo que una discusión más profunda no será beneficiosa para esta sección de comentarios. Si cree que mi respuesta es incorrecta, engañosa o incompleta, entonces usted, o cualquier persona, es bienvenido a editarla y / o rechazarla.
Ya hay una buena respuesta. Simplemente agregue un resultado de referencia para la diferencia de rendimiento de StringBuffer y StringBuild use una nueva instancia en el bucle o use setLength (0) en el bucle.
El resumen es: En un gran bucle
StringBuilder es mucho más rápido que StringBuffer
Crear una nueva instancia de StringBuilder en bucle no tiene ninguna diferencia con setLength (0). (setLength (0) tiene una ventaja muy, muy pequeña que la de crear una nueva instancia).
StringBuffer es más lento que StringBuilder al crear una nueva instancia en bucle
setLength (0) de StringBuffer es extremadamente más lento que crear una nueva instancia en bucle.
Punto de referencia muy simple (acabo de cambiar manualmente el código y hacer una prueba diferente):
publicclassStringBuilderSpeed{publicstaticfinalchar ch[]=newchar[]{'a','b','c','d','e','f','g','h','i'};publicstaticvoid main(String a[]){int loopTime =99999999;long startTime =System.currentTimeMillis();StringBuilder sb =newStringBuilder();for(int i =0; i < loopTime; i++){for(char c : ch){
sb.append(c);}
sb.setLength(0);}long endTime =System.currentTimeMillis();System.out.println("Time cost: "+(endTime - startTime));}
}
Nueva instancia de StringBuilder en bucle: costo de tiempo: 3693, 3862, 3624, 3742
Conjunto de StringBuilder Longitud: Coste de tiempo: 3465, 3421, 3557, 3408
Nueva instancia de StringBuffer en bucle: costo de tiempo: 8327, 8324, 8284
StringBuffer setLength Costo de tiempo: 22878, 23017, 22894
Nuevamente StringBuilder setLength para asegurar que mi laboratorio no tenga algún problema para usar tan largo para StringBuffer setLength :-) Costo de tiempo: 3448
Respuestas:
Una opción es utilizar el método de eliminación de la siguiente manera:
Otra opción (limpiador de bits) usa setLength (int len) :
Consulte Javadoc para obtener más información:
fuente
La forma más sencilla de reutilizar
StringBuffer
es utilizar el métodosetLength()
public void setLength(int newLength)
Puede tener el caso como
fuente
setLength
lugar desetlength
.Tienes dos opciones:
O use:
O usar:
NOTA
Evite declarar objetos
StringBuffer
uStringBuilder
objetos dentro del ciclo, de lo contrario, creará nuevos objetos con cada iteración. La creación de objetos requiere recursos del sistema, espacio y también lleva tiempo. Por lo tanto, a largo plazo, evite declararlos dentro de un bucle si es posible.fuente
fuente
Sugiero crear uno nuevo
StringBuffer
(o incluso mejorStringBuilder
) para cada iteración. La diferencia de rendimiento es realmente insignificante, pero su código será más corto y sencillo.fuente
Uso:
para mayor legibilidad, creo que esta es la mejor solución.
fuente
Ya hay una buena respuesta. Simplemente agregue un resultado de referencia para la diferencia de rendimiento de StringBuffer y StringBuild use una nueva instancia en el bucle o use setLength (0) en el bucle.
El resumen es: En un gran bucle
Punto de referencia muy simple (acabo de cambiar manualmente el código y hacer una prueba diferente):
}
Nueva instancia de StringBuilder en bucle: costo de tiempo: 3693, 3862, 3624, 3742
Conjunto de StringBuilder Longitud: Coste de tiempo: 3465, 3421, 3557, 3408
Nueva instancia de StringBuffer en bucle: costo de tiempo: 8327, 8324, 8284
StringBuffer setLength Costo de tiempo: 22878, 23017, 22894
Nuevamente StringBuilder setLength para asegurar que mi laboratorio no tenga algún problema para usar tan largo para StringBuffer setLength :-) Costo de tiempo: 3448
fuente
Creo que este código es más rápido.
fuente