Pregunta

Las cadenas son inmutables, es decir, una vez que se han creado, no se pueden cambiar.

Entonces, ¿esto significa que tomaría más memoria si agrega cosas con + = que si crea un StringBuffer y agrega texto a eso?

Si usa + =, crearía un nuevo 'objeto' cada vez que debe guardarse en la memoria, ¿no?

¿Fue útil?

Solución

Sí, creará un nuevo objeto cada vez con + =. Sin embargo, eso no significa que siempre sea algo incorrecto. Depende de si desea ese valor como una cadena, o si solo lo va a usar para construir la cadena aún más.

Si realmente quiere el resultado de x + y como una cadena, entonces también podría usar la concatenación de cadenas. Sin embargo, si realmente va a (por ejemplo) hacer un ciclo y agregar otra cadena, y otra, etc., solo necesita el resultado como una cadena al final, entonces StringBuffer / StringBuilder son el camino a seguir. De hecho, el bucle es realmente donde StringBuilder vale la pena por la concatenación de cadenas: la diferencia de rendimiento para 5 o incluso 10 concatenaciones directas será bastante pequeña, pero para miles se vuelve mucho peor, básicamente porque obtienes O (N 2 ) complejidad con concatenación frente a complejidad O (N) con StringBuilder.

En Java 5 y superior, básicamente debería usar StringBuilder, no está sincronizado, pero casi siempre está bien; es muy raro querer compartir uno entre los hilos.

Tengo un artículo sobre todo esto que puede resultarle útil.

Otros consejos

La regla general es simple:

Si está ejecutando concatenaciones en un bucle, no use +=

Si no ejecuta concatenaciones en un bucle, usar + = simplemente no importa. (A menos que sea una aplicación de rendimiento crítico

En Java 5 o posterior, StringBuffer es seguro para subprocesos y, por lo tanto, tiene algunos gastos generales que no debe pagar a menos que lo necesite. StringBuilder tiene la misma API pero no es segura para subprocesos (es decir, solo debe usarla internamente en un solo subproceso).

Sí, si está creando cadenas grandes, es más eficiente usar StringBuilder. Probablemente no valga la pena pasar StringBuilder o StringBuffer como parte de su API. Esto es demasiado confuso.

Estoy de acuerdo con todas las respuestas publicadas anteriormente, pero le ayudará un poco a comprender más sobre la forma en que se implementa Java. La JVM utiliza StringBuffers internamente para compilar el operador String + (De StringBuffer Javadoc ):

  

Las memorias intermedias de cadenas son utilizadas por   compilador para implementar el binario   operador de concatenación de cadenas +. por   ejemplo, el código:

     x = "a" + 4 + "c"
     

se compila con el equivalente de:

     x = new StringBuffer().append("a").append(4).append("c")
                           .toString()

Asimismo, x + = " alguna cadena nueva " es equivalente a x = x + " alguna cadena nueva " . ¿Ves a dónde voy con esto?

Si está haciendo muchas concatenaciones de String, usar StringBuffer aumentará su rendimiento, pero si solo está haciendo un par de concatenaciones de String simples, el compilador de Java probablemente lo optimizará para usted, y no notará una diferencia en el rendimiento

Sí La cadena es inmutable. Para uso ocasional, + = está bien. Si la operación + = es intensiva, debe recurrir a StringBuilder.

Pero el recolector de basura terminará liberando las cadenas viejas una vez que no haya referencias a ellas

Exactamente. Sin embargo, debe usar un StringBuilder si la seguridad de subprocesos no es un problema.

Como nota al margen: puede haber varios objetos String que usen el mismo carácter de respaldo []; por ejemplo, cada vez que use substring (), no se creará un nuevo carácter [] que haga que su uso sea bastante eficiente.

Además, los compiladores pueden hacer alguna optimización por usted. Por ejemplo, si lo haces

static final String FOO = "foo";
static final String BAR = "bar"; 

String getFoobar() {
  return FOO + BAR; // no string concatenation at runtime
}

No me sorprendería si el compilador usara StringBuilder internamente para optimizar la concatenación de String cuando sea posible, si no es así, tal vez en el futuro.

Creo que se basa en el GC para recopilar la memoria con la cadena abandonada. Por lo tanto, hacer + = con el generador de cadenas será definitivamente más rápido si tiene mucha operación en la manipulación de cadenas. Pero no debería ser un problema para la mayoría de los casos.

Sí, lo haría y es exactamente por eso que debe usar StringBuffer para concatenar muchas cadenas.

También tenga en cuenta que desde Java 5 también debería preferir StringBuilder la mayor parte del tiempo. Es solo una especie de StringBuffer no sincronizado.

Tienes razón en que las cadenas son inmutables, por lo que si estás tratando de conservar memoria mientras haces muchas concatenaciones de cadenas, deberías usar StringBuilder en lugar de + =.

Sin embargo, puede que no te importe. Los programas están escritos para sus lectores humanos, por lo que puede ir con claridad. Si es importante que optimices, primero debes crear un perfil. A menos que su programa tenga un gran peso hacia la actividad de la cadena, probablemente habrá otros cuellos de botella.

No

No usará más memoria. Sí, se crean nuevos objetos, pero los viejos se reciclan. Al final, la cantidad de memoria utilizada es la misma.

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