Notas de estudio de la clase String (Parte 2): concatenación de cadenas y aprendizaje de StringBuilder y StringBuffer

Este artículo presenta el método de empalme de cadenas de la clase String y el análisis de eficiencia del empalme de cadenas, así como los métodos comunes y las diferencias de las clases StringBuilder y StringBuffer que pueden modificar el contenido de la cadena y, finalmente, presenta dos preguntas clásicas de entrevistas de cadenas.

1. Resumen de clase de cadena

1. Aprendizaje de métodos comunes de cadenas -> 2. Inmutabilidad de cadenas y conjunto de constantes de cadenas -> StringBuilder y StringBuffer

La clase String es una clase que se utiliza para describir y manipular cadenas en Java.
Los dos últimos blogs introdujeron los métodos comúnmente utilizados y las características de String: el contenido de String es inmutable y el conjunto de cadenas constantes. Si está interesado, puede ir y echa un vistazo...

2. StringBuilder y StringBuffer

StringBulder y StringBuffer son clases que operan en cadenas como String.
Después de aprender String, sabemos que el contenido de String es inmutable. Modificar el contenido de String creará una nueva cadena y la devolverá.

Sin embargo, crear un nuevo objeto String lleva más tiempo y espacio que modificar la cadena original, y la eficacia es mucho menor.

Por lo tanto, StringBuilder y StringBuffer proporcionados en Java son clases especialmente utilizadas para modificar cadenas en su lugar, y todas pueden convertirse ay desde la clase String.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
A través del código fuente, podemos ver que los métodos de estas dos clases son más o menos los mismos, y ambos heredan la clase AbstractStringBuilder

inserte la descripción de la imagen aquí
En la parte inferior de la clase AbstractStringBuilder, hay una referencia de matriz de valores y una variable de conteo, a las que se puede acceder en StringBuilder y StringBuffer sin ser modificadas por privado y final.

La matriz de valores mantiene el contenido de la cadena y el conteo registra la cantidad de caracteres válidos en el valor, es decir, la longitud real de la cadena.

(Debido a que la longitud de la matriz de caracteres a la que apunta el valor es el espacio para almacenar la cadena actualmente, y hay espacio reservado para agregar nuevos caracteres, etc., el conteo registra la longitud real de la cadena)

Debido a las características inmutables de String, para facilitar la modificación de cadenas, Java también proporciona las clases StringBuilder y StringBuffer. La mayoría de las funciones de estas dos clases son las mismas.

1. Concatenación de cadenas

Proporcione métodos concat y join en el método String para empalmar cadenas

inserte la descripción de la imagen aquí

concat es un método miembro que conecta el contenido de un objeto de cadena con otro objeto de cadena para devolver un nuevo objeto de cadena
inserte la descripción de la imagen aquí

join es un método de miembro estático. El primer parámetro del método es la cadena delimitada para la conexión, y las siguientes 2 ~ n cadenas se utilizan para la conexión, que se unirán y separarán por un parámetro (cada segmento de la cadena separados por la conexión, si solo hay un párrafo, el separador no se mostrará), y finalmente devuelva el objeto de cadena concatenado

inserte la descripción de la imagen aquí

Sin embargo, los métodos anteriores no tienen la función de empalmar datos de otros tipos de datos en cadenas, por lo que al usar estos métodos, los datos de otros tipos que no sean cadenas deben empalmarse y convertirse en cadenas antes de empalmarse.

En Java, el tipo String usa + para conectar datos de cadena String y cualquier tipo de datos para que sea simple, rápido y directo el empalme en un nuevo objeto de cadena.
Ejemplo:

public static void main(String[] args) {
    
    

        System.out.println("12"+3);
        System.out.println(3+"12");
        System.out.println(1+2+"12");
        System.out.println("12"+1+2);
        System.out.println(false+"12"+true);
        //代码输出结果是什么?
    }

inserte la descripción de la imagen aquí
Usando la operación + entre los datos de tipo de cadena y cualquier tipo de datos, los datos se pueden empalmar en un nuevo objeto de cadena.

Pero preste atención a la prioridad del operador, 1+2+"12" es calcular 1+2 primero y el resultado es 3, luego 3+"12" se empalma en la cadena "312"

"12"+1+2, primero "12"+1 se empalma en una cadena "121" y luego +2 se empalma en una cadena "1212"

los datos de tipo booleano pueden participar en el empalme de cadenas

""+12 puede formar 12 dígitos empalmados en una cadena "12"

El empalme de cadenas se puede realizar rápidamente a través del signo +, lo cual es muy conveniente y nos permite cambiar rápidamente el tipo de datos básico a un tipo de cadena

StringBuilder y StringBuffer también pueden implementar el empalme de cadenas, que debe llamar a su método de adición interno:

public static void main(String[] args) {
    
    
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append(1+2);
        stringBuilder.append(12);
        System.out.println(stringBuilder);
        stringBuilder.append(3);
        System.out.println(stringBuilder);
        stringBuilder.append(false);
        System.out.println(stringBuilder);
 }

inserte la descripción de la imagen aquí

Se puede ver que cualquier tipo de datos se puede empalmar en una cadena usando el método de agregar del objeto StringBuilder,
inserte la descripción de la imagen aquí
y el último retorno en el método de agregar es el propio objeto StringBuilder, y no se crea ningún objeto nuevo...

En términos de eficiencia operativa, ¿cuál es mejor usar + y otros empalmes de datos, StringBuiler y el método de adición del tipo String?

En este momento, puede usar System.currentTimeMillis(), un método en Java para calcular el tiempo de ejecución interno, para tomar una operación de diferencia para probar el tiempo de ejecución de estos tres...
Ejemplo:

public static void main(String[] args) {
    
    
        long start = System.currentTimeMillis();  // 计算当前内部运行时间
        String s = "";

        for(int i = 0; i < 10000; ++i){
    
    
            s += i;                             //字符串类型 加任意基本数据类型 都会拼接成一个新字符串再给s引用接收
        }   // 每+=一次 会额外创建三个对象
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        start = System.currentTimeMillis();
        StringBuffer sbf = new StringBuffer("");  // 需要加锁解锁
        for(int i = 0; i < 10000; ++i){
    
    
            sbf.append(i);                     //对字符串内的数组进行操作 不会创建额外字符串
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);
        start = System.currentTimeMillis();
        StringBuilder sbd = new StringBuilder();
        for(int i = 0; i < 10000; ++i){
    
    
            sbd.append(i);                 //对字符串内的数组进行操作 不会创建额外字符串
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);
    }

inserte la descripción de la imagen aquí
Se puede estimar aproximadamente ejecutando los resultados: Eficiencia de empalme: String<StringBuffer<StringBuilder

¿Por qué el tipo String que usa + para la concatenación de cadenas es mucho más lento que StringBuilder y StringBuffer?

Desmonte este archivo a través del archivo de bytecode javap -c, y podrá ver lo que se ha hecho en la parte inferior usando el signo +. Usar
inserte la descripción de la imagen aquí
+ para empalmar es esencialmente crear primero un nuevo objeto StringBuilder y luego llamar al método append para agregar el s string a él. , y luego llame a append para agregar i, y finalmente llame al método toString para regresar ~

inserte la descripción de la imagen aquí
Y StringBuilder reescribe el método toString, su función es instanciar un nuevo objeto String,
pasar la matriz a la que apunta la referencia de matriz de valor de AbstractStringBuilder heredada por StringBuilder y 0, contar como parámetros para llamar a su método de construcción,

La función es crear un objeto String cuyo contenido es el contenido entre 0 y el recuento del objeto de matriz al que apunta el valor (nota: el valor en String es la nueva matriz de valores a la que apunta)

Se puede ver que usar el signo + para concatenar cadenas usa el método de agregar del objeto StringBuilder en la parte inferior, y finalmente devuelve un nuevo objeto String...

En el código anterior, 10,000 i se empalman a través del signo + usando el bucle for, y se crearán un objeto StringBuilder y un objeto String para cada empalme Se puede ver que se necesitan tantos objetos nuevos para completar esta operación , y los que no están puntiagudos deben reciclarse Objeto de cadena, consume mucho

La instancia directa del objeto StringBuilder agrega el contenido de la cadena a través de append. Una vez que se completa toda la adición, solo necesita convertir el objeto StringBuilder en un objeto String para una operación. En esta operación, solo se instancian dos objetos adicionales y el la sobrecarga es menor que la del signo +.

Por lo tanto: cuando se usa una gran cantidad de operaciones de agregar cadenas, no se recomienda usar el operador + para empalmar, su rendimiento es mucho menor que usar StringBuilder para agregar empalmes y usar StringBuilder es más eficiente que otros métodos de empalme

("1"+"2" constantes de cadena se concatenan con el signo +, y la adición anterior no se realizará, y la capa subyacente se considerará directamente como una cadena "12")

2. Métodos comunes y diferencias entre StringBuilder y StringBuffer

Tanto StringBuilder como StringBuffer pueden modificar cadenas, y la mayoría de sus métodos internos son los mismos. Los
siguientes son algunos métodos de uso común que pueden modificar el contenido de la cadena, como:

método efecto
adjuntar() Agregar al final, que es equivalente a += de String, y se pueden agregar: variables de boolean, char, char[], double, float, int, long, Object, String, StringBuff
void setCharAt(índice int,char ch) Establezca el carácter en la posición de índice en ch
insertar (compensación int, Cadena str) Insertar en la posición de desplazamiento: ocho tipos de clase base y tipo de cadena y datos de tipo de objeto
deleteCharAt(índice int) Eliminar el carácter de posición de índice
eliminar (intstart, int end) Eliminar los caracteres en el intervalo [inicio, fin)
reemplazar (intstart, int end, String str) Reemplace los caracteres en [inicio, fin) con str
contrarrestar() invertir la cadena en su lugar
Encadenar() Devuelve el contenido como un objeto String

Los anteriores son los métodos comúnmente utilizados por StringBulider y StringBuffer para modificar el contenido de la cadena. También hay algunos métodos como la clase Stirng, como indexOf(). Puede aprender más sobre esto usted mismo.

Dado que la mayoría de los métodos son iguales, ¿cuál es la diferencia específica entre estas dos clases?

Debido a que la clase String no puede modificar la cadena, su diseño puede hacer que los subprocesos sean más seguros. Cada subproceso llama a un método para crear un nuevo objeto de cadena, y StringBuilder puede modificar el contenido de la cadena, lo que resultará en múltiples subprocesos. Llamar simultáneamente a un método puede crear algunos problemas... este es el momento de resolver este problema de subprocesos inseguros

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Se puede ver en el código fuente que la mayoría de los métodos en StringBuffer están decorados con la palabra clave sincronizada (sincronización). El método modificado por esta palabra clave es un método sincronizado, que es seguro para subprocesos, lo que significa que en el caso de múltiples subprocesos, diferentes subprocesos simultáneamente Cuando se llama a este método, se bloqueará. Solo un subproceso puede ejecutar este método a la vez, y otros subprocesos solo pueden ejecutar este método uno por uno después de ejecutar este método y desbloquearlo.

Cuando los objetos anteriores StringBuffer y StringBuilder empalman 10,000 i, StringBuilder es un poco más eficiente que él, y también porque StringBuffer necesita realizar operaciones de bloqueo y desbloqueo al ejecutar métodos, lo que también consume recursos...

Por lo tanto, la clase StringBuffer se usa en situaciones de subprocesos múltiples para modificar objetos de cadena, mientras que StringBuilder se usa en situaciones de un solo subproceso.

3. Pregunta de la entrevista: ¿Cuántos objetos crea el siguiente código?

 public static void main(String[] args) {
    
    

        String str=new String("123");  // 创建多少个对象
        String str1=new String("1"+"2")+new String("3"); //创建多少个对象
//以上程序在运行时字符串常量都是第一次出现字符串常量池并不存在程序中的常量字符串
    }

Cuando el programa se está ejecutando, codifique con str un objeto "123" y guárdelo en el grupo de constantes de cadena, new String() un objeto; finalmente cree dos objetos String

En str1, primero cree un nuevo objeto StringBuilder y luego un nuevo objeto String(), "1"+"2" se programa directamente en "12", que es un objeto String, y luego se empalma en StringBuilder, y luego en el nuevo objeto String, luego " 3" Un objeto se empalma en el objeto StringBuilder, y finalmente StringBuilder llama aString y devuelve un nuevo objeto String, y finalmente 1 nuevo objeto StringBuilder y cinco objetos String

Tenga en cuenta que el último contenido de cadena aceptado por str1 es 123, pero es diferente de "123" en el grupo de constantes de cadena. El grupo de
constantes de cadena almacena su constante de cadena "123" en tiempo de compilación, mientras que str1 acepta la cadena concatenada posterior 123.

inserte la descripción de la imagen aquí

4. Preguntas de la entrevista: similitudes y diferencias entre String, StringBuilder y StringBuffer

Las tres son clases utilizadas para describir la manipulación de cadenas.

El contenido de la clase String es inmutable, y todas las operaciones para modificar el contenido de String son para crear un nuevo objeto String

, los contenidos de StringBuilder y StringBuffer son variables y se usan a menudo cuando se modifican con frecuencia los contenidos de las cadenas.

La mayoría de las funciones de StringBuffer y StringBuilder son similares

StringBuffer usa el procesamiento síncrono, que es una operación segura para subprocesos, mientras que StringBuilder no usa el procesamiento síncrono, que es una operación no segura para subprocesos.

3. Resumen

Este artículo presenta el método de concatenación de cadenas (el método de miembro concat de String y el operador de unión + signo de la concatenación de miembros de clase de StringBuilder y la concatenación de anexos de StringBuffer), así como la eficiencia de varios métodos de empalme y el análisis de desensamblaje subyacente, la mayoría de StringBuffer y StringBuilder El método de modificar el contenido y sus diferencias, así como las preguntas de la entrevista y el análisis de las dos cadenas de caracteres principales

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/lch1552493370/article/details/130654863
Recomendado
Clasificación