JavaRush /Blogue Java /Random-PT /Substitua string em Java

Substitua string em Java

Publicado no grupo Random-PT
No trabalho de um programador, muitas vezes algumas tarefas ou seus componentes podem ser repetidos. Portanto, hoje gostaria de abordar um tema que é frequentemente encontrado no trabalho diário de qualquer desenvolvedor Java. Substitua string em Java - 1Vamos supor que você receba uma determinada string de um determinado método. E tudo parece bom, mas tem alguma coisinha que não combina com você. Por exemplo, o separador não é adequado e você precisa de outro (ou não precisa). O que pode ser feito em tal situação? Naturalmente, use os métodos replaceda classe String.

Substituição de string Java

O tipo objeto Stringpossui quatro variações do método de substituição replace:
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
O objetivo de todos esses métodos é o mesmo - substituir parte de uma string por outra string. Vamos dar uma olhada neles. 1.replace(char, char) String replace(char oldChar, char newChar) - substitui todas as ocorrências do caractere do primeiro argumento oldCharpelo segundo - newChar. Neste exemplo, substituiremos a vírgula por ponto e vírgula:
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Saída do console:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Substitui cada subsequência de uma sequência que corresponde a uma sequência especificada de caracteres por uma sequência de caracteres de substituição.
String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
Conclusão:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) - Substitui a primeira substring que corresponde à expressão regular especificada por uma string de substituição. Ao usar uma expressão regular inválida, você pode capturar uma PatternSyntaxException (o que não é bom). Neste exemplo, vamos substituir o nome do robô campeão:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Saída do console:
In JavaRush, Amigo the best, Diego is Java God
Como podemos ver, apenas a primeira ocorrência de “Diego” mudou, mas as subsequentes permaneceram de fora – ou seja, intocadas. 4. replaceAll()em Java String replaceAll(String regex, String replacement) - este método substitui todas as ocorrências de uma substring em uma string regexpor replacement. Uma expressão regular pode ser usada como primeiro argumento regex. Como exemplo, vamos tentar realizar a substituição anterior por nomes, mas com um novo método:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Saída do console:
In JavaRush, Amigo the best, Amigo is Java God
Como podemos ver, todos os símbolos foram totalmente substituídos pelos necessários. Acho que o Amigo vai ficar satisfeito =)

Expressões regulares

Foi dito acima que é possível substituir usando uma expressão regular. Primeiro, vamos esclarecer o que é uma expressão regular? Expressões regulares são uma linguagem formal para busca e manipulação de substrings em texto, baseada no uso de metacaracteres (curingas). Simplificando, é um padrão de caracteres e metacaracteres que define uma regra de pesquisa. Por exemplo: \D- um modelo que descreva qualquer carácter não digital; \d— define qualquer caractere numérico, que também pode ser descrito como [0-9]; [a-zA-Z]— um modelo que descreve caracteres latinos de a a z, sem distinção entre maiúsculas e minúsculas; Considere a aplicação em um método replaceAllde classe String:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("\\s[a-zA-Z]{5}\\s", " Amigo ");
System.out.println(value);
Saída do console:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— descreve uma palavra de 5 caracteres latinos cercados por espaços. Conseqüentemente, este modelo é substituído pela string que passamos.

Substituição de regex Java

Basicamente, para usar expressões regulares em Java, os recursos do java.util.regex. As principais aulas são:
  1. Pattern- uma classe que fornece uma versão compilada de uma expressão regular.
  2. Matcher— esta classe interpreta o padrão e determina correspondências na string que recebe.
Normalmente, essas duas classes funcionam em conjunto. Então, como será o nosso objeto anterior, mas com a ajuda de Matchere 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);
E nossa conclusão será a mesma:
In JavaRush, Amigo the best, Amigo is Java God
Você pode ler mais sobre expressões regulares neste artigo .

Alternativa para substituir tudo

Não há dúvida de que os métodos replaceimpressionam Stringmuito, mas não se pode ignorar o fato de que Stringse trata de immutableum objeto, ou seja, não pode ser alterado após sua criação. Portanto, quando substituímos algumas partes de uma string usando métodos replace, não alteramos o objeto String, mas criamos um novo a cada vez, com o conteúdo necessário. Mas criar um novo objeto a cada vez leva muito tempo, não é? Especialmente quando a questão não é alguns objetos, mas algumas centenas, ou mesmo milhares. Quer queira quer não, você começa a pensar em alternativas. E que alternativas temos? Substitua string em Java - 2Hmm... Quando se trata de Stringsua propriedade immutable, você imediatamente pensa em alternativas, mas não immutable, ou seja, StringBuilder/StringBuffer . Como lembramos, na verdade essas classes não diferem, exceto que StringBuffersão otimizadas para uso em um ambiente multithread, portanto, StringBuilderfuncionam um pouco mais rápido no uso de thread único. Com base nisso, hoje usaremos StringBuilder. Esta classe tem muitos métodos interessantes, mas especificamente agora estamos interessados ​​em replace. StringBuilder replace(int start, int end, String str)— este método substitui caracteres em uma substring desta sequência por caracteres na string especificada. A substring começa no início especificado e continua até o caractere no final do índice -1ou até o final da sequência, se tal caractere não existir. Vejamos um exemplo:
StringBuilder strBuilder = new StringBuilder("Java Rush");
strBuilder.replace(5, 9, "God");
System.out.println(strBuilder);
Conclusão:
Java God
Como você pode ver, indicamos o intervalo em que queremos escrever a string, e escrevemos uma substring em cima do que está no intervalo. Então, usando a ajuda, StringBuilderrecriaremos um análogo do método replaceall java. Como será:
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();
}
É assustador à primeira vista, mas com um pouco de compreensão você pode entender que nem tudo é tão complicado e é bastante lógico.Temos três argumentos:
  • str— uma linha na qual queremos substituir algumas substrings;
  • oldStr— representação de substrings que iremos substituir;
  • newStr- com o que iremos substituí-lo.
ifPrecisamos do primeiro para verificar os dados recebidos e, se a string strestiver oldStrvazia ou a nova substring newStrfor igual à antiga oldStr, a execução do método não terá sentido. Portanto, retornamos a string original - str. newStrEm seguida, verificamos null, e se for esse o caso, então o convertemos em um formato de string vazio que é mais conveniente para nós - "". Depois temos a declaração das variáveis ​​que precisamos:
  • comprimento total da string str;
  • comprimento da substring oldStr;
  • objeto StringBuilderde uma string compartilhada.
Iniciamos um loop que deve ser executado um número de vezes igual ao comprimento total da string (mas, muito provavelmente, isso nunca acontecerá). Usando o método de classe StringBuilder- indexOf- descobrimos o índice da primeira ocorrência da substring em que estamos interessados. Infelizmente, gostaria de ressaltar que ele indexOfnão funciona com expressões regulares, portanto nosso método final só funcionará com ocorrências de strings (( Se esse índice for igual a -1, então não há mais ocorrências dessas ocorrências no objeto atual StringBuilder, então saímos do método com o resultado de interesse: ele está contido em nosso StringBuilder, para o qual convertemos String, usando toString. Se nosso índice for igual -1na primeira iteração do loop, então a substring que precisa ser substituída não estava no geral string inicialmente. Portanto, em tal situação, simplesmente retornamos a string geral. Em seguida temos e o método descrito acima é usado replacepara StringBuilderusar o índice encontrado da ocorrência para indicar as coordenadas da substring a ser substituída. Este loop será executado quantas vezes forem encontradas substrings que precisam ser substituídas. Se a string consistir apenas no caractere que precisa ser substituído, então somente neste caso teremos O loop será executado completamente e obteremos o resultado StringBuilderconvertido em uma string. Precisamos verificar a exatidão desse método, certo? Vamos escrever um teste que verifica o funcionamento do método em diversas situações:
@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, "");
}
Pode ser dividido em 7 testes separados, cada um dos quais será responsável pelo seu próprio caso de teste. Depois de lançado, veremos que é verde, ou seja, um sucesso. Bem, isso parece ser tudo. Embora espere, dissemos acima que este método será muito mais rápido replaceAllque o String. Bem, vamos dar uma olhada:
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 seguir, esse código foi executado três vezes e obtivemos os seguintes resultados: Saída do console:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
Como podemos ver, em média nosso método é 5 vezes mais produtivo que a replaceAllaula clássica! StringBem, finalmente, vamos fazer a mesma verificação, mas, por assim dizer, em vão. Em outras palavras, no caso em que nenhuma correspondência for encontrada. Vamos substituir a string de pesquisa de "tyu"para "--". Três execuções produziram os seguintes resultados: Saída do console:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
Em média, o desempenho nos casos em que nenhuma correspondência foi encontrada aumentou 8,8 vezes! Substitua string em Java - 4
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION