Pregunta

Dadas las 2 implementaciones toString() abajo, los cuales se prefiere uno:

public String toString(){
    return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}

o

public String toString(){
    StringBuilder sb = new StringBuilder(100);
    return sb.append("{a:").append(a)
          .append(", b:").append(b)
          .append(", c:").append(c)
          .append("}")
          .toString();
}

Más importante aún, dado que sólo tenemos 3 propiedades que no podría hacer una diferencia, pero ¿en qué momento habría que cambiar de concat + a StringBuilder?

¿Fue útil?

Solución

Version 1 es preferible porque es más corto y el compilador de hecho convertirlo en la versión 2 - ninguna diferencia en absoluto el rendimiento

.
  

Lo más importante dado que sólo tenemos 3   propiedades que podrían no hacer una   diferencia, pero ¿en qué punto se   cambio de concat al constructor?

En el punto en que estés concatenar en un bucle -. Eso es por lo general cuando el compilador no puede sustituir StringBuilder por sí mismo

Otros consejos

La clave es si usted está escribiendo un solo concatenación en un solo lugar o acumulando con el tiempo.

En el ejemplo que diste, no hay ningún punto en el uso de StringBuilder explícitamente. (Mira el código compilado para su primer caso.)

Sin embargo, si usted está construyendo una cadena, por ejemplo, dentro de un bucle, utilice StringBuilder.

Para aclarar, en el supuesto de que hugeArray contiene miles de cuerdas, código como este:

...
String result = "";
for (String s : hugeArray) {
    result = result + s;
}

es mucho tiempo y memoria de desperdicio en comparación con:

...
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
    sb.append(s);
}
String result = sb.toString();

Yo prefiero:

String.format( "{a: %s, b: %s, c: %s}", a, b, c );

... porque es corto y fácil de leer.

Me no optimizar este para la velocidad a menos que lo utilice dentro de un bucle con un alto recuento de repetición y han medido la diferencia de rendimiento.

Estoy de acuerdo, que si usted tiene a la salida de una gran cantidad de parámetros, esta forma puede prestarse a confusión (como uno de los comentarios dicen). En este caso me gustaría cambiar a una forma más fácil de leer (tal vez usando ToStringBuilder de Apache-Commons -. tomado de la respuesta de mate b) e ignorar el rendimiento de nuevo

En la mayoría de los casos, no verá una diferencia real entre los dos enfoques, pero es fácil de construir un peor de los casos como éste:

public class Main
{
    public static void main(String[] args)
    {
        long now = System.currentTimeMillis();
        slow();
        System.out.println("slow elapsed " + (System.currentTimeMillis() - now) + " ms");

        now = System.currentTimeMillis();
        fast();
        System.out.println("fast elapsed " + (System.currentTimeMillis() - now) + " ms");
    }

    private static void fast()
    {
        StringBuilder s = new StringBuilder();
        for(int i=0;i<100000;i++)
            s.append("*");      
    }

    private static void slow()
    {
        String s = "";
        for(int i=0;i<100000;i++)
            s+="*";
    }
}

La salida es:

slow elapsed 11741 ms
fast elapsed 7 ms

El problema es que a + = Añadir a una cadena reconstruye una nueva cadena, por lo que cuesta algo lineal a la longitud de sus cadenas (suma de ambos).

Así que - a su pregunta:

El segundo enfoque sería más rápido, pero es menos fácil de leer y más difícil de mantener. Como ya he dicho, en su caso específico es probable que no vea la diferencia.

También tuve choque con mi jefe en el hecho de si se debe utilizar o append + .Como que están utilizando Anexar (todavía no puedo averiguar como se dice cada vez que se crea un nuevo objeto). Así que pensé que hacer algunos R & D.Although Me encanta Michael Borgwardt explicación, pero sólo quería mostrar una explicación si alguien realmente necesita saber en el futuro.

/**
 *
 * @author Perilbrain
 */
public class Appc {
    public Appc() {
        String x = "no name";
        x += "I have Added a name" + "We May need few more names" + Appc.this;
        x.concat(x);
        // x+=x.toString(); --It creates new StringBuilder object before concatenation so avoid if possible
        //System.out.println(x);
    }

    public void Sb() {
        StringBuilder sbb = new StringBuilder("no name");
        sbb.append("I have Added a name");
        sbb.append("We May need few more names");
        sbb.append(Appc.this);
        sbb.append(sbb.toString());
        // System.out.println(sbb.toString());
    }
}

y desmontaje de clase por encima sale como

 .method public <init>()V //public Appc()
  .limit stack 2
  .limit locals 2
met001_begin:                                  ; DATA XREF: met001_slot000i
  .line 12
    aload_0 ; met001_slot000
    invokespecial java/lang/Object.<init>()V
  .line 13
    ldc "no name"
    astore_1 ; met001_slot001
  .line 14

met001_7:                                      ; DATA XREF: met001_slot001i
    new java/lang/StringBuilder //1st object of SB
    dup
    invokespecial java/lang/StringBuilder.<init>()V
    aload_1 ; met001_slot001
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    ldc "I have Added a nameWe May need few more names"
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    aload_0 ; met001_slot000
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lan\
g/StringBuilder;
    invokevirtual java/lang/StringBuilder.toString()Ljava/lang/String;
    astore_1 ; met001_slot001
  .line 15
    aload_1 ; met001_slot001
    aload_1 ; met001_slot001
    invokevirtual java/lang/String.concat(Ljava/lang/String;)Ljava/lang/Strin\
g;
    pop
  .line 18
    return //no more SB created
met001_end:                                    ; DATA XREF: met001_slot000i ...

; ===========================================================================

;met001_slot000                                ; DATA XREF: <init>r ...
    .var 0 is this LAppc; from met001_begin to met001_end
;met001_slot001                                ; DATA XREF: <init>+6w ...
    .var 1 is x Ljava/lang/String; from met001_7 to met001_end
  .end method
;44-1=44
; ---------------------------------------------------------------------------


; Segment type: Pure code
  .method public Sb()V //public void Sb
  .limit stack 3
  .limit locals 2
met002_begin:                                  ; DATA XREF: met002_slot000i
  .line 21
    new java/lang/StringBuilder
    dup
    ldc "no name"
    invokespecial java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    astore_1 ; met002_slot001
  .line 22

met002_10:                                     ; DATA XREF: met002_slot001i
    aload_1 ; met002_slot001
    ldc "I have Added a name"
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 23
    aload_1 ; met002_slot001
    ldc "We May need few more names"
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 24
    aload_1 ; met002_slot001
    aload_0 ; met002_slot000
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lan\
g/StringBuilder;
    pop
  .line 25
    aload_1 ; met002_slot001
    aload_1 ; met002_slot001
    invokevirtual java/lang/StringBuilder.toString()Ljava/lang/String;
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 28
    return
met002_end:                                    ; DATA XREF: met002_slot000i ...


;met002_slot000                                ; DATA XREF: Sb+25r
    .var 0 is this LAppc; from met002_begin to met002_end
;met002_slot001                                ; DATA XREF: Sb+9w ...
    .var 1 is sbb Ljava/lang/StringBuilder; from met002_10 to met002_end
  .end method
;96-49=48
; ---------------------------------------------------------------------------

A partir de los dos códigos anteriores se puede ver Michael se right.In cada caso sólo se crea un objeto SB.

Desde Java 1.5, simple una concatenación línea con "+" y StringBuilder.append () generar exactamente el mismo código de bytes.

Así que por el bien de la legibilidad del código, utilice "+".

2 excepciones:

  • entorno multiproceso: StringBuffer
  • concatenación de bucles: StringBuilder / StringBuffer

Uso última versión de Java (1.8) del desmontaje (javap -c) muestra la optimización introducida por el compilador. + así sb.append() va a generar código muy similar. Sin embargo, valdrá la pena inspeccionar el comportamiento si estamos utilizando + en un bucle.

Adición de cadenas utilizando + en un bucle for

Java:

public String myCatPlus(String[] vals) {
    String result = "";
    for (String val : vals) {
        result = result + val;
    }
    return result;
}

ByteCode: (for bucle extracto)

12: iload         5
14: iload         4
16: if_icmpge     51
19: aload_3
20: iload         5
22: aaload
23: astore        6
25: new           #3                  // class java/lang/StringBuilder
28: dup
29: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
32: aload_2
33: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: aload         6
38: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: invokevirtual #6                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
44: astore_2
45: iinc          5, 1
48: goto          12

Adición de cadenas utilizando stringbuilder.append

Java:

public String myCatSb(String[] vals) {
    StringBuilder sb = new StringBuilder();
    for(String val : vals) {
        sb.append(val);
    }
    return sb.toString();
}

ByteCdoe: (for bucle extracto)

17: iload         5
19: iload         4
21: if_icmpge     43
24: aload_3
25: iload         5
27: aaload
28: astore        6
30: aload_2
31: aload         6
33: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: pop
37: iinc          5, 1
40: goto          17
43: aload_2

Hay un poco de mirando diferencia sin embargo. En primer caso, donde se utilizó +, se crea nueva StringBuilder para cada bucle de iteración y el resultado generado se almacena al hacer una llamada toString() (29 a 41). Así que va a generar cadenas intermedias que su realidad no es necesario durante el uso del operador + en bucle for.

En Java 9 la versión 1 debe ser más rápido, ya que se convierte en invokedynamic llamada. Más detalles se pueden encontrar en PEC-280 :

  

La idea es reemplazar toda la danza StringBuilder append con una simple llamada a invokedynamic java.lang.invoke.StringConcatFactory, que acepte los valores en la necesidad de concatenación.

Apache Commons-Lang tiene una clase ToStringBuilder que es muy fácil de usar. Se hace un buen trabajo de tanto manejar el append-lógica, así como el formato de cómo quiere que su toString para mirar.

public void toString() {
     ToStringBuilder tsb =  new ToStringBuilder(this);
     tsb.append("a", a);
     tsb.append("b", b)
     return tsb.toString();
}

devolverá una salida que se parece a com.blah.YourClass@abc1321f[a=whatever, b=foo].

O en una forma más condensada utilizando el encadenamiento:

public void toString() {
     return new ToStringBuilder(this).append("a", a).append("b", b").toString();
}

O si desea utilizar la reflexión para incluir todos los campos de la clase:

public String toString() {
    return ToStringBuilder.reflectionToString(this);
}

También puede personalizar el estilo de la ToString si lo desea.

Por motivos de rendimiento, se desalentado el uso de += (concatenación String). La razón por la cual es: String Java es un inmutable, cada vez que una nueva concatenación se realiza una nueva String se crea (el nuevo tiene una huella digital diferente a la anterior ya en el grupo de cadena ). La creación de nuevas cadenas ejerce presión sobre la GC y ralentiza el programa: la creación de objetos es caro.

A continuación código debería hacerlo más práctico y claro al mismo tiempo.

public static void main(String[] args) 
{
    // warming up
    for(int i = 0; i < 100; i++)
        RandomStringUtils.randomAlphanumeric(1024);
    final StringBuilder appender = new StringBuilder();
    for(int i = 0; i < 100; i++)
        appender.append(RandomStringUtils.randomAlphanumeric(i));

    // testing
    for(int i = 1; i <= 10000; i*=10)
        test(i);
}

public static void test(final int howMany) 
{
    List<String> samples = new ArrayList<>(howMany);
    for(int i = 0; i < howMany; i++)
        samples.add(RandomStringUtils.randomAlphabetic(128));

    final StringBuilder builder = new StringBuilder();
    long start = System.nanoTime();
    for(String sample: samples)
        builder.append(sample);
    builder.toString();
    long elapsed = System.nanoTime() - start;
    System.out.printf("builder - %d - elapsed: %dus\n", howMany, elapsed / 1000);

    String accumulator = "";
    start = System.nanoTime();
    for(String sample: samples)
        accumulator += sample;
    elapsed = System.nanoTime() - start;
    System.out.printf("concatenation - %d - elapsed: %dus\n", howMany, elapsed / (int) 1e3);

    start = System.nanoTime();
    String newOne = null;
    for(String sample: samples)
        newOne = new String(sample);
    elapsed = System.nanoTime() - start;
    System.out.printf("creation - %d - elapsed: %dus\n\n", howMany, elapsed / 1000);
}

Los resultados de una carrera se presentan a continuación.

builder - 1 - elapsed: 132us
concatenation - 1 - elapsed: 4us
creation - 1 - elapsed: 5us

builder - 10 - elapsed: 9us
concatenation - 10 - elapsed: 26us
creation - 10 - elapsed: 5us

builder - 100 - elapsed: 77us
concatenation - 100 - elapsed: 1669us
creation - 100 - elapsed: 43us

builder - 1000 - elapsed: 511us
concatenation - 1000 - elapsed: 111504us
creation - 1000 - elapsed: 282us

builder - 10000 - elapsed: 3364us 
concatenation - 10000 - elapsed: 5709793us
creation - 10000 - elapsed: 972us

No tener en cuenta los resultados para 1 concatenación (JIT aún no estaba haciendo su trabajo), y por el 10 concatenaciones la penalización de rendimiento es relevante; durante miles de concatenaciones, la diferencia es enorme.

Las lecciones aprendidas de este experimento muy rápido (fácilmente reproducible con el código anterior): nunca utilice la += para concatenar cadenas juntas, incluso en casos muy básicas que se necesitan unas pocas concatenaciones (como se ha dicho, la creación de nuevas cadenas es caro de todos modos y ejerce presión sobre la GC).

Hacer el método toString tan legible como sea posible!

La única excepción a esto en mi libro es si se puede prueba a mí que consume recursos significativos :) (Sí, esto significa perfilado)

Tenga en cuenta también que el 5 de Java compilador genera código más rápido que el método escrito a mano "StringBuffer" que se utiliza en versiones anteriores de Java. Si utiliza "+" esto y mejoras en el futuro viene de forma gratuita.

Parece que hay cierto debate si el uso de StringBuilder sigue siendo necesaria con los compiladores actuales. Así que pensé que daré mis 2 centavos de experiencia.

Tengo un conjunto de resultados JDBC de 10k registros (sí, necesito todos ellos en un solo lote.) Utilizando el operador + tarda unos 5 minutos en mi máquina con Java 1.8. Usando stringBuilder.append("") tarda menos de un segundo para la misma consulta.

Así que la diferencia es enorme. Dentro de un bucle StringBuilder es mucho más rápido.

Vea el siguiente ejemplo:

//java8
static void main(String[] args) {
    case1();//str.concat
    case2();//+=
    case3();//StringBuilder
}

static void case1() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    String str = "";
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str = str.concat(UUID.randomUUID()+"---");
        saveTime(savedTimes, startTime);
    }
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");
}

static void case2() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    String str = "";
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str+=UUID.randomUUID()+"---";
        saveTime(savedTimes, startTime);
    }        
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");
}

static void case3() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    StringBuilder str = new StringBuilder("");
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str.append(UUID.randomUUID()+"---");
        saveTime(savedTimes, startTime);
    }        
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");

}

static void saveTime(List<Long> executionTimes, long startTime) {
        executionTimes.add(System.currentTimeMillis()-startTime);
        if(executionTimes.size()%CALC_AVG_EVERY == 0) {
            out.println("average time for "+executionTimes.size()+" concatenations: "+
                    NumberFormat.getInstance().format(executionTimes.stream().mapToLong(Long::longValue).average().orElseGet(()->0))+
                    " ms avg");
            executionTimes.clear();
        }
}

Salida:

  

tiempo promedio de 10000 concatenaciones: 0,096 ms promedio
  tiempo promedio de 10000 concatenaciones: 0,185 ms promedio
  tiempo promedio de 10000 concatenaciones: 0,327 ms promedio
  tiempo promedio de 10000 concatenaciones: 0,501 ms promedio
  tiempo promedio de 10000 concatenaciones: 0,656 ms promedio
  Creado cadena de longitud: 1950000 en 17745 ms
  tiempo promedio de 10000 concatenaciones: 0,21 ms promedio
  tiempo promedio de 10000 concatenaciones: 0,652 ms promedio
  tiempo promedio de 10000 concatenaciones: 1.129 ms promedio
  tiempo promedio de 10000 concatenaciones: 1.727 ms promedio
  tiempo promedio de 10000 concatenaciones: 2.302 ms promedio
  Creado cadena de longitud: 1950000 en 60279 ms
  tiempo promedio de 10000 concatenaciones: 0,002 ms promedio
  tiempo promedio de 10000 concatenaciones: 0,002 ms promedio
  tiempo promedio de 10000 concatenaciones: 0,002 ms promedio
  tiempo promedio de 10000 concatenaciones: 0,002 ms promedio
  tiempo promedio de 10000 concatenaciones: 0,002 ms promedio
  Creado cadena de longitud: 1950000 en 100 ms

A medida que aumenta la longitud de cadena, también lo hace el tiempo de concatenación.
Ahí es donde definitivamente se necesita la StringBuilder.
Como se ve, la concatenación:. UUID.randomUUID()+"---", no afecta realmente a la hora

PS: no creo Cuándo utilizar StringBuilder en Java es realmente un duplicado de éste.
Esta pregunta se habla de toString() que la mayoría de las veces no realiza concatenaciones de grandes cadenas.

En cuanto al rendimiento concatenación de cadenas usando '+' es más costoso porque tiene que hacer una copia de toda nueva cadena desde Las cadenas son inmutables en Java. Esto juega un papel particular, si la concatenación es muy frecuente, por ejemplo: dentro de un bucle. Lo que sigue es lo que mi idea sugiere cuando intento hacer algo así:

introducir descripción de la imagen aquí

Reglas Generales:

  • Dentro de una sola asignación de cadena, mediante la concatenación de cadenas está muy bien.
  • Si está bucle para construir un gran bloque de datos de caracteres, vaya para StringBuffer.
  • Uso + = en una cadena siempre va a ser menos eficiente que el uso de un StringBuffer, por lo que debería hacer sonar las campanas de advertencia - pero en ciertos casos, la optimización de ganado será insignificante en comparación con los problemas de legibilidad, a fin de utilizar su sentido común.

Aquí está una agradable Jon Skeet el blog en torno a este tema.

¿Puedo señalar que si usted va a iterar sobre una colección y el uso de StringBuilder, es posible que desee comprobar hacia fuera Apache Commons Lang y StringUtils.join () (en diferentes sabores)?

A pesar de los resultados, se ahorrará tener que crear StringBuilders y para los bucles de lo que parece ser el millonésima tiempo.

He comparado cuatro enfoque diferente para comparar el rendimiento. Yo no sé exactamente lo que sucede con la GC, pero lo importante para mí es el tiempo. Compilador es factor importante utilizado here.i jdk1.8.0_45 bajo la plataforma window8.1.

concatWithPlusOperator = 8
concatWithBuilder = 130
concatWithConcat = 127
concatStringFormat = 3737
concatWithBuilder2 = 46


public class StringConcatenationBenchmark {

private static final int MAX_LOOP_COUNT = 1000000;

public static void main(String[] args) {

    int loopCount = 0;
    long t1 = System.currentTimeMillis();
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithPlusOperator();
        loopCount++;
    }
    long t2 = System.currentTimeMillis();
    System.out.println("concatWithPlusOperator = " + (t2 - t1));

    long t3 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithBuilder();
        loopCount++;
    }
    long t4 = System.currentTimeMillis();
    System.out.println("concatWithBuilder = " + (t4 - t3));

    long t5 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithConcat();
        loopCount++;
    }
    long t6 = System.currentTimeMillis();
    System.out.println("concatWithConcat = " + (t6 - t5));

    long t7 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatStringFormat();
        loopCount++;
    }
    long t8 = System.currentTimeMillis();
    System.out.println("concatStringFormat = " + (t8 - t7));

    long t9 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithBuilder2();
        loopCount++;
    }
    long t10 = System.currentTimeMillis();
    System.out.println("concatWithBuilder2 = " + (t10 - t9));
}

private static void concatStringFormat() {
    String s = String.format("%s %s %s %s ", "String", "String", "String", "String");
}

private static void concatWithConcat() {
    String s = "String".concat("String").concat("String").concat("String");
}

private static void concatWithBuilder() {
    StringBuilder builder=new StringBuilder("String");
    builder.append("String").append("String").append("String");
    String s = builder.toString();
}

private static void concatWithBuilder2() {
    String s = new StringBuilder("String").append("String").append("String").append("String").toString();
}

private static void concatWithPlusOperator() {
    String s = "String" + "String" + "String" + "String";
}
}

Esto es lo que registré Java8

  • Uso de la concatenación de cadenas
  • Uso StringBuilder

    long time1 = System.currentTimeMillis();
    usingStringConcatenation(100000);
    System.out.println("usingStringConcatenation " + (System.currentTimeMillis() - time1) + " ms");
    
    time1 = System.currentTimeMillis();
    usingStringBuilder(100000);
    System.out.println("usingStringBuilder " + (System.currentTimeMillis() - time1) + " ms");
    
    
    private static void usingStringBuilder(int n)
    {
        StringBuilder str = new StringBuilder();
        for(int i=0;i<n;i++)
            str.append("myBigString");    
    }
    
    private static void usingStringConcatenation(int n)
    {
        String str = "";
        for(int i=0;i<n;i++)
            str+="myBigString";
    }
    
  

Es realmente una pesadilla si está utilizando la concatenación de cadenas para un gran número de cadenas.

usingStringConcatenation 29321 ms
usingStringBuilder 2 ms

Creo que hay que ir con StringBuilder método append. La razón es

  1. El concatenar cadena será crear una nueva cadena objeto cada vez (As String es objeto inmutable), por lo que creará 3 objetos.

  2. Con La Cadena constructor creado sólo un objeto [StringBuilder es muttable] y la cadena más se añade a la misma.

Para las cadenas simples como que prefiero utilizar

"string".concat("string").concat("string");

Con el fin, yo diría que el método preferido para la construcción de una cadena está utilizando StringBuilder, Cadena # concat (), entonces la sobrecarga operador +. StringBuilder es un aumento significativo de rendimiento cuando se trabaja grandes cadenas como usar el operador + es una gran disminución en el rendimiento (gran disminución exponencial a medida que aumenta el tamaño de cuerdas). El único problema con el uso .concat () es que puede lanzar NullPointerExceptions.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top