JavaRush /Java Blog /Random-IT /Sostituisci la stringa in Java

Sostituisci la stringa in Java

Pubblicato nel gruppo Random-IT
Nel lavoro di un programmatore, molto spesso alcuni compiti o i loro componenti possono essere ripetuti. Pertanto, oggi vorrei toccare un argomento che si incontra spesso nel lavoro quotidiano di qualsiasi sviluppatore Java. Sostituisci la stringa in Java - 1Supponiamo che tu riceva una determinata stringa da un determinato metodo. E tutto sembra andare bene, ma c'è qualche piccola cosa che non ti si addice. Ad esempio, il separatore non è adatto e ne serve un altro (o non lo è affatto). Cosa si può fare in una situazione del genere? Naturalmente utilizzate i metodi replacedella classe String.

Sostituzione della stringa Java

L'oggetto tipo Stringha quattro varianti del metodo di sostituzione replace:
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
Lo scopo di tutti questi metodi è lo stesso: sostituire parte di una stringa con un'altra stringa. Diamo un'occhiata più da vicino a loro. 1.replace(char, char) String replace(char oldChar, char newChar) - sostituisce tutte le occorrenze del carattere del primo argomento oldCharcon il secondo - newChar. In questo esempio sostituiremo la virgola con un punto e virgola:
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Uscita console:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Sostituisce ciascuna sottostringa di una stringa che corrisponde a una sequenza di caratteri specificata con una sequenza di caratteri sostitutivi.
String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
Conclusione:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) - Sostituisce la prima sottostringa che corrisponde all'espressione regolare specificata con una stringa sostitutiva. Quando si utilizza un'espressione regolare non valida, è possibile rilevare una PatternSyntaxException (che non è una buona cosa). In questo esempio, sostituiamo il nome del robot campione:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Uscita console:
In JavaRush, Amigo the best, Diego is Java God
Come possiamo vedere, solo la prima voce di “Diego” è cambiata, ma le successive sono rimaste fuori, cioè intatte. 4. replaceAll()in Java String replaceAll(String regex, String replacement) : questo metodo sostituisce tutte le occorrenze di una sottostringa in una stringa regexcon replacement. Come primo argomento è possibile utilizzare un'espressione regolare regex. Ad esempio, proviamo ad eseguire la precedente sostituzione con nomi, ma con un nuovo metodo:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Uscita console:
In JavaRush, Amigo the best, Amigo is Java God
Come possiamo vedere, tutti i simboli sono stati completamente sostituiti con quelli necessari. Penso che Amigo sarà contento =)

Espressioni regolari

Si è detto sopra che è possibile sostituire utilizzando un'espressione regolare. Innanzitutto, chiariamo cos'è un'espressione regolare? Le espressioni regolari sono un linguaggio formale per la ricerca e la manipolazione di sottostringhe nel testo, basato sull'uso di metacaratteri (caratteri jolly). In poche parole, è uno schema di caratteri e metacaratteri che definisce una regola di ricerca. Ad esempio: \D- un modello che descrive qualsiasi carattere non digitale; \d— definisce qualsiasi carattere numerico, che può anche essere descritto come [0-9]; [a-zA-Z]— un modello che descrive i caratteri latini dalla a alla z, senza distinzione tra maiuscole e minuscole; Considera l'applicazione in un metodo replaceAlldi 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);
Uscita console:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— descrive una parola di 5 caratteri latini circondati da spazi. Di conseguenza, questo modello viene sostituito con la stringa che abbiamo passato.

Sostituzione dell'espressione regolare Java

Fondamentalmente, per utilizzare le espressioni regolari in Java, le funzionalità di java.util.regex. Le classi chiave sono:
  1. Pattern- una classe che fornisce una versione compilata di un'espressione regolare.
  2. Matcher— questa classe interpreta il modello e determina le corrispondenze nella stringa che riceve.
In genere, queste due classi funzionano insieme. Quindi, come sarà il nostro oggetto precedente, ma con l'aiuto di 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 la nostra conclusione sarà la stessa:
In JavaRush, Amigo the best, Amigo is Java God
Puoi leggere ulteriori informazioni sulle espressioni regolari in questo articolo .

Alternativa a replaceAll

Non c'è dubbio che i metodi replacesiano Stringmolto impressionanti, ma non si può ignorare il fatto che Stringsi tratta di immutableun oggetto, cioè non può essere modificato dopo la sua creazione. Pertanto, quando sostituiamo alcune parti di una stringa utilizzando i metodi replace, non modifichiamo l'oggetto String, ma ne creiamo ogni volta uno nuovo, con i contenuti necessari. Ma ci vuole molto tempo per creare un nuovo oggetto ogni volta, non è vero? Soprattutto quando la questione non riguarda un paio di oggetti, ma un paio di centinaia o addirittura migliaia. Volenti o nolenti, inizi a pensare alle alternative. E quali alternative abbiamo? Sostituisci la stringa in Java - 2Hmm... Quando si parla della Stringsua proprietà immutable, si pensa immediatamente ad alternative, ma non a immutable, vale a dire StringBuilder/StringBuffer . Come ricordiamo, queste classi in realtà non differiscono, tranne per il fatto che StringBuffersono ottimizzate per l'uso in un ambiente multi-thread, quindi StringBuilderfunzionano un po' più velocemente nell'uso a thread singolo. Sulla base di ciò, oggi utilizzeremo StringBuilder. Questa classe ha molti metodi interessanti, ma nello specifico ora ci interessa replace. StringBuilder replace(int start, int end, String str)— questo metodo sostituisce i caratteri in una sottostringa di questa sequenza con i caratteri nella stringa specificata. La sottostringa inizia dall'inizio specificato e continua fino al carattere alla fine dell'indice -1o fino alla fine della sequenza se tale carattere non esiste. Diamo un'occhiata ad un esempio:
StringBuilder strBuilder = new StringBuilder("Java Rush");
strBuilder.replace(5, 9, "God");
System.out.println(strBuilder);
Conclusione:
Java God
Come puoi vedere, indichiamo l'intervallo in cui vogliamo scrivere la stringa e scriviamo una sottostringa sopra ciò che si trova nell'intervallo. Quindi, utilizzando l'aiuto, StringBuilderricreeremo un analogo del metodo replaceall java. Come apparirà:
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();
}
A prima vista fa paura, ma con un po’ di comprensione puoi capire che tutto non è così complicato e del tutto logico, abbiamo tre argomenti:
  • str— una riga in cui vogliamo sostituire alcune sottostringhe;
  • oldStr— rappresentazione delle sottostringhe che sostituiremo;
  • newStr- con cosa lo sostituiremo.
ifAbbiamo bisogno del primo per controllare i dati in arrivo e se la stringa strè oldStrvuota o la nuova sottostringa newStrè uguale a quella vecchia oldStr, l'esecuzione del metodo non avrà senso. Pertanto, restituiamo la stringa originale - str. Successivamente, controlliamo newStrla presenza di nulle, in tal caso, lo convertiamo in un formato di stringa vuota che è più conveniente per noi - "". Poi abbiamo la dichiarazione delle variabili di cui abbiamo bisogno:
  • lunghezza totale della stringa str;
  • lunghezza della sottostringa oldStr;
  • oggetto StringBuilderda una stringa condivisa.
Iniziamo un ciclo che dovrebbe essere eseguito un numero di volte pari alla lunghezza della stringa totale (ma, molto probabilmente, questo non accadrà mai). Utilizzando il metodo class StringBuilder- indexOf- troviamo l'indice della prima occorrenza della sottostringa che ci interessa. Sfortunatamente, vorrei notare che indexOfnon funziona con le espressioni regolari, quindi il nostro metodo finale funzionerà solo con le occorrenze di stringhe (( Se questo indice è uguale a -1, allora non ci sono più occorrenze di queste occorrenze nell'oggetto corrente StringBuilder, quindi usciamo dal metodo con il risultato che ci interessa: è contenuto nel nostro StringBuilder, che convertiamo in String, utilizzando toString.Se il nostro indice è uguale -1nella prima iterazione del ciclo, allora la sottostringa che deve essere sostituita non era nel generale string inizialmente. Pertanto, in una situazione del genere, restituiamo semplicemente la stringa generale. Successivamente abbiamo e il metodo sopra descritto viene utilizzato replaceper StringBuilderutilizzare l'indice trovato dell'occorrenza per indicare le coordinate della sottostringa da sostituire. Questo ciclo verrà eseguito tante volte quante sono le sottostringhe da sostituire.Se la stringa è composta solo dal carattere da sostituire, solo in questo caso abbiamo Il ciclo verrà eseguito completamente e otterremo il risultato StringBuilderconvertito in una stringa. Dobbiamo verificare la correttezza di questo metodo, giusto? Scriviamo un test che verifica il funzionamento del metodo in varie situazioni:
@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, "");
}
Può essere suddiviso in 7 test separati, ognuno dei quali sarà responsabile del proprio caso di test. Dopo averlo lanciato, vedremo che è green, cioè di successo. Bene, sembra essere tutto. Anche se aspetta, abbiamo detto sopra che questo metodo sarà molto più veloce replaceAlldi String. Bene vediamo:
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);
Successivamente, questo codice è stato eseguito tre volte e abbiamo ottenuto i seguenti risultati: Output della console:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
Come possiamo vedere, mediamente il nostro metodo è 5 volte più produttivo della replaceAlllezione classica! StringBene, infine, eseguiamo lo stesso controllo, ma, per così dire, invano. In altre parole, nel caso in cui non venga trovata alcuna corrispondenza. Sostituiamo la stringa di ricerca da "tyu"a "--". Tre esecuzioni hanno prodotto i seguenti risultati: Output della console:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
In media, la prestazione per i casi in cui non è stata trovata alcuna corrispondenza è aumentata di 8,8 volte! Sostituisci la stringa in Java - 4
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION