java string oop stringbuilder

java - String, StringBuffer y StringBuilder



stringbuffer vs stringbuilder (11)

¿Por favor, dime una situación en tiempo real para comparar String , StringBuffer y StringBuilder ?


¿Quieres decir, por concatenación?

Ejemplo del mundo real: desea crear una nueva cadena a partir de muchas otras .

Por ejemplo para enviar un mensaje:

Cuerda

String s = "Dear " + user.name + "<br>" + " I saw your profile and got interested in you.<br>" + " I''m " + user.age + "yrs. old too"

StringBuilder

String s = new StringBuilder().append.("Dear ").append( user.name ).append( "<br>" ) .append(" I saw your profile and got interested in you.<br>") .append(" I''m " ).append( user.age ).append( "yrs. old too") .toString()

O

String s = new StringBuilder(100).appe..... etc. ... // The difference is a size of 100 will be allocated upfront as fuzzy lollipop points out.

StringBuffer (la sintaxis es exactamente igual que con StringBuilder, los efectos difieren)

Acerca de

StringBuffer vs StringBuilder

Lo primero está sincronizado y luego no lo está.

Por lo tanto, si lo invoca varias veces en un solo subproceso (que es el 90% de los casos), StringBuilder se ejecutará mucho más rápido porque no se detendrá para ver si posee el bloqueo del subproceso.

Por lo tanto, es recomendable usar StringBuilder (a menos que, por supuesto, tenga más de un hilo accediendo a él al mismo tiempo, lo cual es raro)

String compilador puede optimizar la concatenación de String ( con el operador + ) para usar StringBuilder debajo, por lo que ya no es algo de qué preocuparse, en los días pasados ​​de Java, esto era algo que todo el mundo dice que debería evitarse a toda costa, porque cada concatenación creó un nuevo objeto String. Los compiladores modernos ya no hacen esto, pero aún así es una buena práctica usar StringBuilder lugar de usar un compilador "antiguo".

editar

Solo para quien es curioso, esto es lo que hace el compilador para esta clase:

class StringConcatenation { int x; String literal = "Value is" + x; String builder = new StringBuilder().append("Value is").append(x).toString(); }

javap -c StringConcatenation

Compiled from "StringConcatenation.java" class StringConcatenation extends java.lang.Object{ int x; java.lang.String literal; java.lang.String builder; StringConcatenation(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: aload_0 5: new #2; //class java/lang/StringBuilder 8: dup 9: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V 12: ldc #4; //String Value is 14: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 17: aload_0 18: getfield #6; //Field x:I 21: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 24: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 27: putfield #9; //Field literal:Ljava/lang/String; 30: aload_0 31: new #2; //class java/lang/StringBuilder 34: dup 35: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V 38: ldc #4; //String Value is 40: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 43: aload_0 44: getfield #6; //Field x:I 47: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 50: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 53: putfield #10; //Field builder:Ljava/lang/String; 56: return }

Las líneas numeradas del 5 al 27 son para la cadena llamada "literal"

Las líneas numeradas del 31 al 53 son para la cadena llamada "constructor"

No hay diferencia, se ejecuta exactamente el mismo código para ambas cadenas.


Además, StringBuffer es seguro para subprocesos, lo que no es StringBuilder .

Entonces, en una situación en tiempo real cuando diferentes hilos están accediendo a él, StringBuilder podría tener un resultado indeterminista.


En java, String es inmutable. Al ser inmutables, queremos decir que una vez que se crea una Cadena, no podemos cambiar su valor. StringBuffer es mutable. Una vez que se crea un objeto StringBuffer, simplemente agregamos el contenido al valor del objeto en lugar de crear un nuevo objeto. StringBuilder es similar a StringBuffer pero no es seguro para subprocesos. Los métodos de StingBuilder no están sincronizados, pero en comparación con otras cadenas, el Stringbuilder se ejecuta más rápido. Puede aprender la diferencia entre String, StringBuilder y StringBuffer implementándolos.


La diferencia entre String y las otras dos clases es que String es inmutable y las otras dos son clases mutables.

¿Pero por qué tenemos dos clases para el mismo propósito?

La razón es que StringBuffer es Thread safe y StringBuilder no. StringBuilder es una nueva clase en StringBuffer Api y se introdujo en JDK5 y siempre se recomienda si está trabajando en un entorno de un solo hilo, ya que es mucho Faster

Para obtener detalles completos, puede leer http://www.codingeek.com/java/stringbuilder-and-stringbuffer-a-way-to-create-mutable-strings-in-java/


Personalmente, no creo que haya ningún uso del mundo real para StringBuffer . ¿Cuándo querría comunicarme entre varios hilos manipulando una secuencia de caracteres? Eso no suena útil en absoluto, pero quizás aún no haya visto la luz :)


Tenga en cuenta que si está utilizando Java 5 o más reciente, debe usar StringBuilder lugar de StringBuffer . De la documentación de la API:

A partir de la versión JDK 5, esta clase se ha complementado con una clase equivalente diseñada para ser utilizada por un solo hilo, StringBuilder . La clase StringBuilder generalmente se debe usar con preferencia a esta, ya que admite todas las mismas operaciones, pero es más rápida, ya que no realiza ninguna sincronización.

En la práctica, casi nunca usará esto desde varios subprocesos al mismo tiempo, por lo que la sincronización que hace StringBuffer es casi siempre una sobrecarga innecesaria.


Cuerda

La String class representa cadenas de caracteres. Todos los literales de cadena en el programa Java, como "abc" se implementan como instancias de esta clase.

Los objetos de cadena son inmutables una vez que se crean, no podemos cambiarlos. (Las cuerdas son constantes )

  • Si se crea una cadena utilizando un constructor o un método, esas cadenas se almacenarán en la memoria del montón y en SringConstantPool . Pero antes de guardar en el grupo, invoca el método intern() para verificar la disponibilidad del objeto con el mismo contenido en el grupo utilizando el método equals. Si String-copy está disponible en el Pool, devuelve la referencia. De lo contrario, el objeto String se agrega a la agrupación y devuelve la referencia.

    • El lenguaje Java proporciona soporte especial para el operador de concatenación de cadenas ( + ) y para la conversión de otros objetos en cadenas. La concatenación de cadenas se implementa a través de la clase StringBuilder (o StringBuffer) y su método de adición.

    String heapSCP = new String("Yash"); heapSCP.concat("."); heapSCP = heapSCP + "M"; heapSCP = heapSCP + 777; // For Example: String Source Code public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true); }

  • Los literales de cadena se almacenan en StringConstantPool .

    String onlyPool = "Yash";

StringBuilder y StringBuffer son secuencias mutables de caracteres. Eso significa que uno puede cambiar el valor de estos objetos. StringBuffer tiene los mismos métodos que StringBuilder, pero cada método en StringBuffer está sincronizado, por lo que es seguro para subprocesos.

  • Los datos de StringBuffer y StringBuilder solo se pueden crear usando un nuevo operador. Por lo tanto, se almacenan en la memoria del montón.

  • Las instancias de StringBuilder no son seguras para ser utilizadas por múltiples hilos. Si se requiere tal sincronización, se recomienda que se utilice StringBuffer.

    StringBuffer threadSafe = new StringBuffer("Yash"); threadSafe.append(".M"); threadSafe.toString(); StringBuilder nonSync = new StringBuilder("Yash"); nonSync.append(".M"); nonSync.toString();

  • StringBuffer y StringBuilder tienen métodos especiales como., replace(int start, int end, String str) y reverse() .

    NOTA : StringBuffer y SringBuilder son mutables, ya que proporcionan la implementación de la Appendable Interface .

Cuándo usar cuál.

  • Si no va a cambiar el valor cada vez, entonces es mejor usar String Class . Como parte de Generics, si desea ordenar Comparable<T> o comparar valores, vaya a String Class .

    //ClassCastException: java.lang.StringBuffer cannot be cast to java.lang.Comparable Set<StringBuffer> set = new TreeSet<StringBuffer>(); set.add( threadSafe ); System.out.println("Set : "+ set);

  • Si va a modificar el valor cada vez que vaya a StringBuilder, que es más rápido que StringBuffer. Si múltiples hilos están modificando el valor, vaya para StringBuffer.


Diferencia de mutabilidad:

String es inmutable , si intenta modificar sus valores, se crea otro objeto, mientras que StringBuffer y StringBuilder son mutables para que puedan cambiar sus valores.

Diferencia de seguridad del hilo:

La diferencia entre StringBuffer y StringBuilder es que StringBuffer es seguro para subprocesos. Por lo tanto, cuando la aplicación solo se debe ejecutar en un único subproceso, es mejor usar StringBuilder . StringBuilder es más eficiente que StringBuffer .

Situaciones:

  • Si su cadena no va a cambiar, use una clase de cadena porque un objeto de String es inmutable.
  • Si su cadena puede cambiar (ejemplo: mucha lógica y operaciones en la construcción de la cadena) y solo se accederá desde un solo hilo, usar un StringBuilder es suficiente.
  • Si su cadena puede cambiar y se podrá acceder a ella desde varios subprocesos, use un StringBuffer porque StringBuffer es síncrono, por lo que tiene seguridad para subprocesos.

Los basicos:

String es una clase inmutable, no se puede cambiar. StringBuilder es una clase mutable a la que se pueden agregar, que los caracteres se pueden reemplazar o eliminar y, en última instancia, se convierten en StringBuffer es la versión sincronizada original de StringBuilder

Debería preferir StringBuilder en todos los casos en los que tenga un solo hilo que acceda a su objeto.

Los detalles:

También tenga en cuenta que StringBuilder/Buffers no son mágicos, solo usan un Array como un objeto de respaldo y que el Array tiene que ser reasignado cuando se llena. Asegúrese de crear sus objetos StringBuilder/Buffer suficientemente grandes originalmente para que no tengan que cambiar su tamaño constantemente cada vez que se llama a .append() .

El cambio de tamaño puede llegar a ser muy degenerado. Básicamente, cambia el tamaño de la matriz de respaldo a 2 veces su tamaño actual cada vez que se debe ampliar. Esto puede hacer que se asignen grandes cantidades de RAM y no se utilicen cuando las clases de StringBuilder/Buffer comiencen a crecer.

En Java String x = "A" + "B"; utiliza un StringBuilder detrás de las escenas. Entonces, para casos simples, no hay beneficio de declarar los tuyos. Pero si está creando objetos String que son grandes, digamos menos de 4k y luego declare StringBuilder sb = StringBuilder(4096); es mucho más eficiente que la concatenación o el uso del constructor predeterminado, que tiene solo 16 caracteres. Si su String va a ser inferior a 10k, inicialícelo con el constructor a 10k para estar seguro. Pero si se inicializa a 10k, entonces escribe 1 carácter más de 10k, se volverá a asignar y se copiará a una matriz de 20k. Así que inicializar alto es mejor que a bajo.

En el caso de cambio de tamaño automático, en el 17º carácter, la matriz de respaldo se vuelve a asignar y se copia a 32 caracteres; en el 33º carácter, esto vuelve a suceder y se vuelve a asignar y copia la matriz en 64 caracteres. Puede ver cómo esto degenera en muchas reasignaciones y copias, que es lo que realmente está tratando de evitar usando StringBuilder/Buffer en primer lugar.

Esto es del código fuente de JDK 6 para AbstractStringBuilder

void expandCapacity(int minimumCapacity) { int newCapacity = (value.length + 1) * 2; if (newCapacity < 0) { newCapacity = Integer.MAX_VALUE; } else if (minimumCapacity > newCapacity) { newCapacity = minimumCapacity; } value = Arrays.copyOf(value, newCapacity); }

Una buena práctica es inicializar el StringBuilder/Buffer un poco más grande de lo que crees que necesitarás si no sabes de inmediato qué tan grande será el String pero puedes adivinarlo. Una asignación de un poco más de memoria de la que necesita será mejor que muchas reasignaciones y copias.

También tenga cuidado de inicializar un StringBuilder/Buffer con un String ya que solo asignará el tamaño del String + 16 caracteres, que en la mayoría de los casos solo iniciará la reasignación degenerada y el ciclo de copia que está tratando de evitar. Lo siguiente es directamente del código fuente de Java 6.

public StringBuilder(String str) { super(str.length() + 16); append(str); }

Si por casualidad terminas con una instancia de StringBuilder/Buffer que no creaste y no puedes controlar el constructor al que se llama, hay una manera de evitar el degenerado comportamiento de reasignación y copia. Llame a .ensureCapacity() con el tamaño que desea para garantizar que su String resultante se ajuste.

Las alternativas:

Solo como una nota, si estás haciendo una construcción y manipulación de String realmente pesada , hay una alternativa mucho más orientada al rendimiento llamada Ropes .

Otra alternativa es crear una implementación de StringList mediante una StringList de ArrayList<String> , y agregando contadores para rastrear el número de caracteres en cada .append() y otras operaciones de mutación de la lista, luego .toString() para crear un StringBuilder del tamaño exacto que necesita y recorre la lista y genera la salida, incluso puede hacer que StringBuilder una variable de instancia y "almacenar en caché" los resultados de .toString() y solo tiene que volver a generarla cuando algo cambie.

Además, no se olvide de String.format() al crear una salida con formato fijo, que el compilador puede optimizar a medida que lo hacen mejor.


---------------------------------------------------------------------------------- String StringBuffer StringBuilder ---------------------------------------------------------------------------------- Storage Area | Constant String Pool Heap Heap Modifiable | No (immutable) Yes( mutable ) Yes( mutable ) Thread Safe | Yes Yes No Performance | Fast Very slow Fast ----------------------------------------------------------------------------------


  • Usas String cuando una estructura inmutable es apropiada; la obtención de una nueva secuencia de caracteres de una String puede conllevar una penalización de rendimiento inaceptable, ya sea en el tiempo de CPU o en la memoria (la obtención de subcadenas es eficiente en la CPU porque los datos no se copian, pero esto significa que es posible que se asigne una cantidad de datos mucho mayor).
  • Utiliza StringBuilder cuando necesitas crear una secuencia de caracteres mutable, generalmente para concatenar varias secuencias de caracteres juntas.
  • Usted usa StringBuffer en las mismas circunstancias que usaría StringBuilder , pero cuando los cambios en la cadena subyacente deben estar sincronizados (debido a que varias cadenas están leyendo / modificando el búfer de la cadena).

Vea un ejemplo here .