Java Challengers # 2: Comparación de cadenas

Java Challengers # 2: Comparación de cadenas


Como siempre, tenemos mucho retraso para el comienzo del curso, así que ayer tuvimos una segunda lección entre el nuevo hilo "Java Developer" . Pero esto es así, pequeñas cosas en la vida, pero por ahora seguimos publicando una serie de artículos de Java Challengers, cuya traducción ha sido preparada para usted.


En Java, la clase String encapsula una matriz de caracteres ( nota del traductor: con java 9 ya es una matriz de byte , consulte Cadenas compactas en Java 9 ). En términos simples, String es una matriz de caracteres utilizados para componer palabras, oraciones u otras construcciones.


La encapsulación es uno de los conceptos más poderosos en la programación orientada a objetos. Gracias a la encapsulación, no necesita saber cómo funciona la clase String . Solo necesita conocer los métodos de su interfaz.



Cuando observa la clase String en Java, puede ver cómo se encapsula la matriz de caracteres:


 public String(char value[]) { this(value, 0, value.length, null); } 

Para comprender mejor la encapsulación, imagine un objeto físico: una máquina. ¿Necesita saber cómo funciona un automóvil debajo del capó para conducirlo? Por supuesto que no, pero debe saber qué hacen las interfaces del automóvil: el acelerador, los frenos y el volante. Cada una de estas interfaces admite ciertas acciones: aceleración, frenado, girar a la izquierda, girar a la derecha. Lo mismo es cierto en la programación orientada a objetos.


El primer artículo de la serie Java Challengers fue sobre la sobrecarga de métodos, que se usa ampliamente en la clase String . La sobrecarga puede hacer que tus clases sean realmente flexibles:


 public String(String original) {} public String(char value[], int offset, int count) {} public String(int[] codePoints, int offset, int count) {} public String(byte bytes[], int offset, int length, String charsetName) {} //    ... 

En lugar de tratar de entender cómo funciona la clase String , este artículo lo ayudará a comprender lo que hace y cómo usarlo en su código.


¿Qué es un conjunto de cadenas?


La clase String es posiblemente la clase más utilizada en Java. Si creamos un nuevo objeto en la memoria dinámica (montón de memoria) cada vez que usamos String , desperdiciaremos mucha memoria. El conjunto de cadenas resuelve este problema almacenando solo un objeto para cada valor de fila.


cadenas-en-la-cadena-pool


Grupo de líneas en fila


Aunque creamos varias variables de String con los valores Duke y Juggy , solo se crean y almacenan dos objetos en la memoria dinámica (montón). Vea el siguiente ejemplo de código para la prueba. (Recuerde que en Java, el operador " == " se usa para comparar dos objetos y determinar si el mismo objeto es el mismo o no).


 String juggy = "Juggy"; String anotherJuggy = "Juggy"; System.out.println(juggy == anotherJuggy); 

Este código devolverá true porque las dos variables de String apuntan al mismo objeto en el grupo de cadenas. Sus significados son los mismos.


La excepción es el new operador.


Ahora mire este código: se parece al ejemplo anterior, pero hay una diferencia.


 String duke = new String("duke"); String anotherDuke = new String("duke"); System.out.println(duke == anotherDuke); 

Según el ejemplo anterior, puede pensar que este código devolverá true , pero no lo es. Agregar un new operador crea un nuevo objeto String en la memoria. Por lo tanto, la JVM creará dos objetos diferentes.


Métodos nativos

Los métodos nativos en Java son métodos que se compilarán utilizando el lenguaje C, generalmente con el objetivo de administrar la memoria y optimizar el rendimiento.

Agrupaciones de cadenas y método intern()


Para almacenar cadenas en una agrupación, se utiliza un método llamado intercalación de cadenas.


Esto es lo que Javadoc nos dice sobre el método intern() :


  /** *      . * *   ( )   {@code String}. * *    intern,     , *    {@code String},   *  {@link #equals(Object)},     . * ,   {@code String}   *        {@code String}. * *   ,      {@code s}  {@code t}, * {@code s.intern() == t.intern()}  {@code true} *    ,  {@code s.equals(t)}  {@code true}. * *       . *      3.10.5 The Java™ Language Specification. * * @returns ,         , * , ,       . * * @jls 3.10.5 String Literals */ public native String intern(); 

El método intern() se usa para almacenar cadenas en un grupo de cadenas. Primero, verifica si una fila ya creada existe en el grupo. Si no, crea una nueva fila en el grupo. La lógica del grupo de filas se basa en el patrón Flyweight .


Ahora, observe lo que sucede cuando usamos new para crear dos líneas:


 String duke = new String("duke"); String duke2 = new String("duke"); System.out.println(duke == duke2); //    false System.out.println(duke.intern() == duke2.intern()); //    true 

A diferencia del ejemplo anterior con la new palabra clave, en este caso la comparación devolverá true . Esto se debe a que el uso del método intern() garantiza que la cadena se encuentre en el grupo.


Método equals en String clase String


El método equals() se usa para verificar si dos clases son iguales o no. Como equals() se encuentra en la clase Object , cada clase Java la hereda. Pero el método equals() debe ser anulado para que funcione correctamente. Por supuesto, String anula equals() .


Echa un vistazo:


 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (coder() == aString.coder()) { return isLatin1() ? StringLatin1.equals(value, aString.value) : StringUTF16.equals(value, aString.value); } } return false; } 

Como puede ver, el valor de la clase String se compara a través de equals() y no a través de una referencia de objeto. No importa si las referencias a los objetos son diferentes; Las condiciones serán comparadas.


Métodos de String comunes


Hay una cosa más que debe saber antes de resolver el problema de comparación de cadenas.


Considere los métodos más comunes de la clase String :


 //         trim() //     substring(int beginIndex, int endIndex) //    length() //  ,     replaceAll(String regex, String replacement) // ,     CharSequence   contains(CharSequences) 

Resolver el problema de comparación de cadenas


Verifiquemos lo que aprendió sobre la clase String resolviendo un pequeño rompecabezas.


En esta tarea, compara varias líneas usando los conceptos que ha aprendido. Mirando el código a continuación, ¿puedes determinar el valor de cada result variable?


 public class ComparisonStringChallenge { public static void main(String... doYourBest) { String result = ""; result += " powerfulCode ".trim() == "powerfulCode" ? "0" : "1"; result += "flexibleCode" == "flexibleCode" ? "2" : "3"; result += new String("doYourBest") == new String("doYourBest") ? "4" : "5"; result += new String("noBugsProject") .equals("noBugsProject") ? "6" : "7"; result += new String("breakYourLimits").intern() == new String("breakYourLimits").intern() ? "8" : "9"; System.out.println(result); } } 

¿Cuál será la conclusión?


  • A: 02468
  • B: 12469
  • C: 12579
  • D: 12568

La respuesta correcta se da al final del artículo.


Que paso ahora Comprender String comportamiento de las String


En la primera línea vemos:


 result += " powerfulCode ".trim() == "powerfulCode" ? "0" : "1"; 

En este caso, el resultado es false , porque cuando el método trim() elimina espacios, crea una nueva String utilizando el new operador.


A continuación vemos:


 result += "flexibleCode" == "flexibleCode" ? "2" : "3"; 

No hay ningún secreto aquí; las filas son las mismas en el grupo de filas. Esta comparación devuelve true .


Entonces, tenemos:


 result += new String("doYourBest") == new String("doYourBest") ? "4" : "5"; 

El uso de new pistas conduce a la creación de dos nuevas líneas y no importa si sus valores son iguales o no. En este caso, la comparación será false incluso si los valores son los mismos.


Siguiente:


 result += new String("noBugsProject") .equals("noBugsProject") ? "6" : "7"; 

Como usamos el método equals() , se comparará el valor de la cadena, no la instancia del objeto.


En este caso, no importa si hay diferentes objetos o no, ya que se compara el valor. El resultado es true .


Finalmente tenemos:


 result += new String("breakYourLimits").intern() == new String("breakYourLimits").intern() ? "8" : "9"; 

Como viste anteriormente, el método intern() coloca una cadena en un grupo de cadenas. Ambas líneas apuntan al mismo objeto, por lo que en este caso es true .


Errores de cadena comunes


Puede ser difícil determinar si dos líneas apuntan al mismo objeto o no, especialmente cuando las líneas contienen el mismo valor. Es útil recordar que usar new siempre conduce a la creación de un nuevo objeto en la memoria, incluso si los valores de cadena son los mismos.


El uso de métodos de String para comparar referencias de objetos también puede ser complicado. La peculiaridad es que si el método cambia algo en la línea, habrá diferentes referencias a los objetos.


Algunos ejemplos para ayudar a aclarar:


 System.out.println("duke".trim() == "duke".trim()); 

Esta comparación será verdadera porque el método trim() no crea una nueva línea.


 System.out.println(" duke".trim() == "duke".trim()); 

En este caso, el primer método trim() genera una nueva línea, ya que el método hará su trabajo y, por lo tanto, los enlaces serán diferentes.


Finalmente, cuando trim() hace su trabajo, crea una nueva línea:


 //   trim   String new String(Arrays.copyOfRange(val, index, index + len), LATIN1); 

Que recordar acerca de las cuerdas


  • Las filas no son mutables, por lo que el estado de la fila no se puede cambiar.


  • Para ahorrar memoria, la JVM almacena cadenas en un grupo de cadenas. Al crear una nueva línea, la JVM verifica su valor y apunta a un objeto existente. Si el grupo no tiene una fila con este valor, la JVM crea una nueva fila.


  • El operador " == " compara referencias de objetos. El método equals() compara valores de cadena. La misma regla se aplicará a todos los objetos.


  • Al usar el new operador, se creará una nueva línea en el montón (Nota del traductor: está escrito en el original que está en el grupo, pero esto no es así, gracias zagayevskiy ), incluso si hay una línea con el mismo valor.



La respuesta


La respuesta a este problema es D. La conclusión será 12568.


Continuará ...

Source: https://habr.com/ru/post/es428449/


All Articles