JavaRush /Blog Java /Random-ES /Reemplazar cadena en Java

Reemplazar cadena en Java

Publicado en el grupo Random-ES
En el trabajo de un programador, con bastante frecuencia algunas tareas o sus componentes pueden repetirse. Por eso, hoy me gustaría tocar un tema que se encuentra a menudo en el trabajo diario de cualquier desarrollador de Java. Reemplazar cadena en Java - 1Supongamos que recibe una determinada cadena de un determinado método. Y todo parece estar bien, pero hay alguna pequeña cosa que no te conviene. Por ejemplo, el separador no es adecuado y necesita otro (o ninguno). ¿Qué se puede hacer en tal situación? Naturalmente, utilice los métodos replacede la clase String.

Reemplazo de cadena de Java

El tipo objeto Stringtiene cuatro variaciones del método de reemplazo replace:
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
El propósito de todos estos métodos es el mismo: reemplazar parte de una cadena por otra cadena. Echemos un vistazo más de cerca. 1.replace(char, char) String replace(char oldChar, char newChar) - reemplaza todas las apariciones del carácter del primer argumento oldCharcon el segundo - newChar. En este ejemplo, reemplazaremos la coma con un punto y coma:
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Salida de consola:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Reemplaza cada subcadena de una cadena que coincide con una secuencia de caracteres específica con una secuencia de caracteres de reemplazo.
String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
Conclusión:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) - Reemplaza la primera subcadena que coincide con la expresión regular especificada con una cadena de reemplazo. Cuando se utiliza una expresión regular no válida, se puede detectar una excepción PatternSyntaxException (lo cual no es bueno). En este ejemplo, reemplacemos el nombre del robot campeón:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Salida de consola:
In JavaRush, Amigo the best, Diego is Java God
Como podemos ver, sólo la primera entrada de “Diego” ha cambiado, pero las siguientes quedaron omitidas, es decir, intactas. 4. replaceAll()en Java String replaceAll(String regex, String replacement) : este método reemplaza todas las apariciones de una subcadena en una cadena regexcon replacement. Se puede utilizar una expresión regular como primer argumento regex. Como ejemplo, intentemos realizar el reemplazo anterior con nombres, pero con un nuevo método:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Salida de consola:
In JavaRush, Amigo the best, Amigo is Java God
Como podemos ver, todos los símbolos han sido reemplazados completamente por los necesarios. Creo que Amigo estará contento =)

Expresiones regulares

Se dijo anteriormente que es posible reemplazar usando una expresión regular. Primero, aclaremos qué es una expresión regular. Las expresiones regulares son un lenguaje formal para buscar y manipular subcadenas en el texto, basado en el uso de metacaracteres (comodines). En pocas palabras, es un patrón de caracteres y metacaracteres que define una regla de búsqueda. Por ejemplo: \D- una plantilla que describa cualquier carácter no digital; \d— define cualquier carácter numérico, que también puede describirse como [0-9]; [a-zA-Z]— una plantilla que describe los caracteres latinos de la a a la z, sin distinguir entre mayúsculas y minúsculas; Considere la aplicación en un método replaceAllde clase String:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("\\s[a-zA-Z]{5}\\s", " Amigo ");
System.out.println(value);
Salida de consola:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— describe una palabra de 5 caracteres latinos rodeados de espacios. En consecuencia, esta plantilla se reemplaza con la cadena que pasamos.

Reemplazo de expresiones regulares de Java

Básicamente, para utilizar expresiones regulares en Java, las capacidades de java.util.regex. Las clases clave son:
  1. Pattern- una clase que proporciona una versión compilada de una expresión regular.
  2. Matcher— esta clase interpreta el patrón y determina coincidencias en la cadena que recibe.
Normalmente, estas dos clases funcionan en conjunto. Entonces, ¿cómo se verá nuestro objeto anterior, pero con la ayuda de Matchery Pattern:
Pattern pattern = Pattern.compile("\\s[a-zA-Z]{5}\\s");
Matcher matcher = pattern.matcher("In JavaRush, Diego the best, Diego is Java God");
String value = matcher.replaceAll(" Amigo ");
System.out.println(value);
Y nuestra conclusión será la misma:
In JavaRush, Amigo the best, Amigo is Java God
Puede leer más sobre expresiones regulares en este artículo .

Alternativa para reemplazar todo

No hay duda de que los métodos replaceson Stringmuy impresionantes, pero no se puede ignorar el hecho de que Stringes immutableun objeto, es decir, no se puede cambiar después de su creación. Por lo tanto, cuando reemplazamos algunas partes de una cadena usando métodos replace, no cambiamos el objeto String, sino que creamos uno nuevo cada vez, con el contenido necesario. Pero crear un objeto nuevo cada vez lleva mucho tiempo, ¿no es así? Especialmente cuando la cuestión no es un par de objetos, sino un par de cientos, o incluso miles. Quieras o no, empiezas a pensar en alternativas. ¿Y qué alternativas tenemos? Reemplazar cadena en Java - 2Hmm... Cuando se trata de Stringsu propiedad immutable, inmediatamente piensas en alternativas, pero no immutable, a saber, StringBuilder/StringBuffer . Como recordamos, estas clases en realidad no difieren, excepto que StringBufferestán optimizadas para su uso en un entorno de subprocesos múltiples, por lo que StringBuilderfuncionan algo más rápido en el uso de un solo subproceso. En base a esto, hoy usaremos StringBuilder. Esta clase tiene muchos métodos interesantes, pero ahora nos interesa específicamente replace. StringBuilder replace(int start, int end, String str)— este método reemplaza caracteres en una subcadena de esta secuencia con caracteres en la cadena especificada. La subcadena comienza al principio especificado y continúa hasta el carácter al final del índice, -1o hasta el final de la secuencia si dicho carácter no existe. Veamos un ejemplo:
StringBuilder strBuilder = new StringBuilder("Java Rush");
strBuilder.replace(5, 9, "God");
System.out.println(strBuilder);
Conclusión:
Java God
Como puedes ver, indicamos el intervalo en el que queremos escribir la cadena, y escribimos una subcadena encima de lo que hay en el intervalo. Entonces, usando la ayuda, StringBuilderrecrearemos un análogo del método replaceall java. Cómo se verá:
public static String customReplaceAll(String str, String oldStr, String newStr) {

   if ("".equals(str) || "".equals(oldStr) || oldStr.equals(newStr)) {
       return str;
   }
   if (newStr == null) {
       newStr = "";
   }
   final int strLength = str.length();
   final int oldStrLength = oldStr.length();
   StringBuilder builder = new StringBuilder(str);

   for (int i = 0; i < strLength; i++) {
       int index = builder.indexOf(oldStr, i);

       if (index == -1) {
           if (i == 0) {
               return str;
           }
           return builder.toString();
       }
       builder = builder.replace(index, index + oldStrLength, newStr);

   }
       return builder.toString();
}
Da miedo a primera vista, pero con un poco de comprensión se puede entender que no todo es tan complicado y es bastante lógico. Tenemos tres argumentos:
  • str— una línea en la que queremos reemplazar algunas subcadenas;
  • oldStr— representación de subcadenas que reemplazaremos;
  • newStr- con qué lo reemplazaremos.
ifNecesitamos el primero para verificar los datos entrantes, y si la cadena strestá oldStrvacía o la nueva subcadena newStres igual a la anterior oldStr, entonces ejecutar el método no tendrá sentido. Por lo tanto, devolvemos la cadena original - str. A continuación, verificamos newStry null, si este es el caso, lo convertimos a un formato de cadena vacía que sea más conveniente para nosotros: "". Luego tenemos la declaración de las variables que necesitamos:
  • longitud total de la cuerda str;
  • longitud de la subcadena oldStr;
  • objeto StringBuilderde una cadena compartida.
Iniciamos un bucle que debería ejecutarse un número de veces igual a la longitud de la cadena total (pero lo más probable es que esto nunca suceda). Usando el método de clase StringBuilder- indexOf- encontramos el índice de la primera aparición de la subcadena que nos interesa. Desafortunadamente, me gustaría señalar que indexOfno funciona con expresiones regulares, por lo que nuestro método final solo funcionará con apariciones de cadenas (( Si este índice es igual a -1, entonces no hay más apariciones de estas ocurrencias en el objeto actual StringBuilder, entonces salimos del método con el resultado de interés: está contenido en nuestro StringBuilder, al que convertimos Stringusando toString. Si nuestro índice es igual -1en la primera iteración del bucle, entonces la subcadena que necesita ser reemplazada no estaba en el general cadena inicialmente. Por lo tanto, en tal situación, simplemente devolvemos la cadena general. A continuación tenemos y el método descrito anteriormente se utiliza replacepara StringBuilderusar el índice encontrado de la ocurrencia para indicar las coordenadas de la subcadena a reemplazar. Este bucle se ejecutará tantas veces como se encuentren subcadenas que necesitan ser reemplazadas. Si la cadena consta solo del carácter que necesita ser reemplazado, entonces solo en este caso tenemos El bucle se ejecutará por completo y obtendremos el resultado StringBuilderconvertido en una cadena. Necesitamos comprobar la exactitud de este método, ¿verdad? Escribamos una prueba que verifique el funcionamiento del método en diversas situaciones:
@Test
public void customReplaceAllTest() {
   String str = "qwertyuiop__qwertyuiop__";

   String firstCase = Solution.customReplaceAll(str, "q", "a");
   String firstResult = "awertyuiop__awertyuiop__";
   assertEquals(firstCase, firstResult);

   String secondCase = Solution.customReplaceAll(str, "q", "ab");
   String secondResult = "abwertyuiop__abwertyuiop__";
   assertEquals(secondCase, secondResult);

   String thirdCase = Solution.customReplaceAll(str, "rtyu", "*");
   String thirdResult = "qwe*iop__qwe*iop__";
   assertEquals(thirdCase, thirdResult);

   String fourthCase = Solution.customReplaceAll(str, "q", "");
   String fourthResult = "wertyuiop__wertyuiop__";
   assertEquals(fourthCase, fourthResult);

   String fifthCase = Solution.customReplaceAll(str, "uio", "");
   String fifthResult = "qwertyp__qwertyp__";
   assertEquals(fifthCase, fifthResult);

   String sixthCase = Solution.customReplaceAll(str, "", "***");
   assertEquals(sixthCase, str);

   String seventhCase = Solution.customReplaceAll("", "q", "***");
   assertEquals(seventhCase, "");
}
Se puede dividir en 7 pruebas independientes, cada una de las cuales será responsable de su propio caso de prueba. Al lanzarlo veremos que está en color verde, es decir, exitoso. Bueno, eso parece ser todo. Aunque espera, dijimos anteriormente que este método será mucho más rápido replaceAllque String. Bueno, echemos un vistazo:
String str = "qwertyuiop__qwertyuiop__";
long firstStartTime = System.nanoTime();

for (long i = 0; i < 10000000L; i++) {
   str.replaceAll("tyu", "#");
}

double firstPerformance = System.nanoTime() - firstStartTime;

long secondStartTime = System.nanoTime();

for (long i = 0; i < 10000000L; i++) {
   customReplaceAll(str, "tyu", "#");
}

double secondPerformance = System.nanoTime() - secondStartTime;

System.out.println("Performance ratio  - " +  firstPerformance / secondPerformance);
A continuación, este código se ejecutó tres veces y obtuvimos los siguientes resultados: Salida de la consola:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
Como podemos ver, en promedio nuestro método es 5 veces más productivo que la replaceAllclase clásica. StringBueno, finalmente, hagamos la misma verificación, pero, por así decirlo, en vano. En otras palabras, en el caso de que no se encuentre ninguna coincidencia. Reemplacemos la cadena de búsqueda de "tyu"a "--". Tres ejecuciones arrojaron los siguientes resultados: Salida de la consola:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
En promedio, el rendimiento en los casos en los que no se encontraron coincidencias aumentó 8,8 veces. Reemplazar cadena en Java - 4
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION