JavaRush /Java Blog /Random-TL /Palitan ang string sa Java

Palitan ang string sa Java

Nai-publish sa grupo
Sa gawain ng isang programmer, kadalasan ang ilang mga gawain o ang kanilang mga bahagi ay maaaring paulit-ulit. Samakatuwid, ngayon nais kong hawakan ang isang paksa na madalas na nakatagpo sa pang-araw-araw na gawain ng anumang developer ng Java. Palitan ang string sa Java - 1Ipagpalagay natin na nakatanggap ka ng isang tiyak na string mula sa isang tiyak na pamamaraan. At lahat ng bagay tungkol dito ay tila maganda, ngunit mayroong ilang maliit na bagay na hindi nababagay sa iyo. Halimbawa, ang separator ay hindi angkop, at kailangan mo ng isa pa (o hindi sa lahat). Ano ang maaaring gawin sa ganoong sitwasyon? Naturally, gamitin ang mga pamamaraan replaceng klase String.

Palitan ng Java string

Ang uri ng bagay Stringay may apat na pagkakaiba-iba ng paraan ng pagpapalit replace:
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
Ang layunin ng lahat ng mga pamamaraan na ito ay pareho - palitan ang bahagi ng isang string ng isa pang string. Tingnan natin ang mga ito nang mas malapitan. 1.replace(char, char) String replace(char oldChar, char newChar) - pinapalitan ang lahat ng paglitaw ng karakter ng unang argumento oldCharng pangalawa - newChar. Sa halimbawang ito, papalitan namin ang kuwit ng semicolon:

String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Output ng console:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Pinapalitan ang bawat substring ng isang string na tumutugma sa isang tinukoy na sequence ng mga character na may isang sequence ng mga kapalit na character.

String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
Konklusyon:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) - Pinapalitan ang unang substring na tumutugma sa tinukoy na regular na expression ng isang kapalit na string. Kapag gumagamit ng di-wastong regular na expression, maaari kang makakuha ng PatternSyntaxException (na hindi magandang bagay). Sa halimbawang ito, palitan natin ang pangalan ng kampeon na robot:

String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Output ng console:
In JavaRush, Amigo the best, Diego is Java God
Tulad ng nakikita natin, ang unang paglitaw lamang ng "Diego" ay nagbago, ngunit ang mga sumunod ay nanatiling naiwan-iyon ay, hindi nagalaw. 4. replaceAll()sa Java String replaceAll(String regex, String replacement) - pinapalitan ng paraang ito ang lahat ng paglitaw ng isang substring sa isang string regexng replacement. Maaaring gamitin ang isang regular na expression bilang unang argumento regex. Bilang halimbawa, subukan nating gawin ang nakaraang pagpapalit ng mga pangalan, ngunit gamit ang isang bagong paraan:

String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Output ng console:
In JavaRush, Amigo the best, Amigo is Java God
Tulad ng nakikita natin, ang lahat ng mga simbolo ay ganap na pinalitan ng mga kinakailangan. Sa tingin ko matutuwa si Amigo =)

Mga Regular na Ekspresyon

Sinabi sa itaas na posibleng palitan gamit ang isang regular na expression. Una, linawin natin sa ating sarili kung ano ang isang regular na expression? Ang mga regular na expression ay isang pormal na wika para sa paghahanap at pagmamanipula ng mga substring sa teksto, batay sa paggamit ng mga metacharacter (wildcards). Sa madaling salita, ito ay isang pattern ng mga character at metacharacter na tumutukoy sa isang panuntunan sa paghahanap. Halimbawa: \D- isang template na naglalarawan ng anumang hindi digital na character; \d— tumutukoy sa anumang numerong karakter, na maaari ding ilarawan bilang [0-9]; [a-zA-Z]— isang template na naglalarawan ng mga Latin na character mula a hanggang z, case insensitive; Isaalang-alang ang aplikasyon sa isang paraan replaceAllng klase String:

String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("\\s[a-zA-Z]{5}\\s", " Amigo ");
System.out.println(value);
Output ng console:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— naglalarawan ng salita ng 5 Latin na character na napapalibutan ng mga puwang. Alinsunod dito, ang template na ito ay pinalitan ng string na ipinasa namin.

Palitan ng Java regex

Karaniwan, upang gumamit ng mga regular na expression sa Java, ang mga kakayahan ng java.util.regex. Ang mga pangunahing klase ay:
  1. Pattern- isang klase na nagbibigay ng pinagsama-samang bersyon ng isang regular na expression.
  2. Matcher— binibigyang-kahulugan ng klase na ito ang pattern at tinutukoy ang mga tugma sa string na natatanggap nito.
Karaniwan, ang dalawang klase na ito ay gumagana nang magkasama. Kaya, ano ang magiging hitsura ng aming nakaraang bagay, ngunit sa tulong ng Matcherat 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);
At ang aming konklusyon ay magiging pareho:
In JavaRush, Amigo the best, Amigo is Java God
Maaari kang magbasa nang higit pa tungkol sa mga regular na expression sa artikulong ito .

Alternatibong palitan angLahat

Walang alinlangan na ang mga pamamaraan replaceay Stringnapaka-kahanga-hanga, ngunit hindi maaaring balewalain ng isa ang katotohanan na Stringito ay immutableisang bagay, iyon ay, hindi ito mababago pagkatapos ng paglikha nito. Samakatuwid, kapag pinalitan namin ang ilang bahagi ng isang string gamit ang mga pamamaraan replace, hindi namin binabago ang bagay String, ngunit lumikha ng bago sa bawat oras, na may mga kinakailangang nilalaman. Ngunit ang paglikha ng isang bagong bagay sa bawat oras ay tumatagal ng mahabang panahon, hindi ba? Lalo na kapag ang tanong ay hindi isang pares ng mga bagay, ngunit isang pares ng daan-daan, o kahit libu-libo. Willy-nilly, magsisimula kang mag-isip tungkol sa mga alternatibo. At anong mga alternatibo ang mayroon tayo? Palitan ang string sa Java - 2Hmm... Pagdating sa Stringproperty nito immutable, nag-iisip ka kaagad ng mga alternatibo, ngunit hindi immutable, namely StringBuilder/StringBuffer . Tulad ng naaalala namin, ang mga klase na ito ay hindi aktwal na naiiba, maliban na ang StringBuffermga ito ay na-optimize para sa paggamit sa isang multi-threaded na kapaligiran, kaya StringBuildermedyo mas mabilis ang mga ito sa paggamit ng single-threaded. Batay dito, ngayon ay gagamitin namin StringBuilder. Ang klase na ito ay may maraming mga kawili-wiling pamamaraan, ngunit partikular na ngayon kami ay interesado sa replace. StringBuilder replace(int start, int end, String str)— pinapalitan ng pamamaraang ito ang mga character sa isang substring ng sequence na ito ng mga character sa tinukoy na string. Magsisimula ang substring sa tinukoy na simula at magpapatuloy hanggang sa character sa dulo ng index, -1o hanggang sa dulo ng sequence kung walang ganoong character. Tingnan natin ang isang halimbawa:

StringBuilder strBuilder = new StringBuilder("Java Rush");
strBuilder.replace(5, 9, "God");
System.out.println(strBuilder);
Konklusyon:
Java God
Tulad ng nakikita mo, ipinapahiwatig namin ang pagitan kung saan nais naming isulat ang string, at magsulat ng isang substring sa ibabaw ng kung ano ang nasa pagitan. Kaya, gamit ang tulong, StringBuildergagawa kami ng isang analogue ng pamamaraan replaceall java. Paano ito magiging hitsura:

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();
}
Nakakatakot sa unang tingin, ngunit sa kaunting pag-unawa ay mauunawaan mo na ang lahat ay hindi masyadong kumplikado at medyo lohikal. Mayroon kaming tatlong argumento:
  • str— isang linya kung saan gusto naming palitan ang ilang mga substring;
  • oldStr— representasyon ng mga substring na papalitan namin;
  • newStr- kung ano ang ipapalit natin dito.
ifKailangan namin ang una upang suriin ang papasok na data, at kung ang string stray alinman oldStrsa walang laman, o ang bagong substring newStray katumbas ng luma oldStr, kung gayon ang pagpapatupad ng pamamaraan ay magiging walang kabuluhan. Samakatuwid, ibinabalik namin ang orihinal na string - str. Susunod, sinusuri namin newStrang null, at kung ito ang kaso, pagkatapos ay i-convert namin ito sa isang walang laman na format ng string na mas maginhawa para sa amin - "". Pagkatapos ay mayroon kaming deklarasyon ng mga variable na kailangan namin:
  • kabuuang haba ng string str;
  • haba ng substring oldStr;
  • bagay StringBuildermula sa isang nakabahaging string.
Nagsisimula kami ng isang loop na dapat tumakbo nang maraming beses na katumbas ng haba ng kabuuang string (ngunit, malamang, hindi ito mangyayari). Gamit ang paraan ng klase StringBuilder- indexOf- nalaman natin ang index ng unang paglitaw ng substring na interesado tayo. Sa kasamaang palad, nais kong tandaan na indexOfhindi ito gumagana sa mga regular na expression, kaya ang aming panghuling pamamaraan ay gagana lamang sa mga paglitaw ng mga string (( Kung ang index na ito ay katumbas ng -1, pagkatapos ay wala nang mga paglitaw ng mga pangyayaring ito sa kasalukuyang bagay StringBuilder, kaya lumabas kami sa pamamaraan na may resulta ng interes: ito ay nakapaloob sa aming StringBuilder, na kung saan namin iko-convert sa String, gamit ang toString. Kung ang aming index ay pantay -1sa unang pag-ulit ng loop, kung gayon ang substring na kailangang palitan ay wala sa pangkalahatan string sa simula. Samakatuwid, sa ganoong sitwasyon, ibinabalik lang namin ang pangkalahatang string. Susunod na mayroon kami at ang pamamaraan na inilarawan sa itaas ay ginagamit replacepara sa StringBuilderpaggamit ng nahanap na index ng pangyayari upang ipahiwatig ang mga coordinate ng substring na papalitan. Ang loop na ito ay tatakbo kasing daming beses na natagpuan ang mga substring na kailangang palitan. Kung ang string ay binubuo lamang ng character na kailangang palitan, kung gayon sa kasong ito lamang mayroon tayong ganap na tatakbo ang loop at makukuha natin ang resulta na StringBuilderma-convert sa isang string. Kailangan nating suriin ang kawastuhan ng pamamaraang ito, tama ba? Sumulat tayo ng isang pagsubok na sumusuri sa pagpapatakbo ng pamamaraan sa iba't ibang sitwasyon:

@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, "");
}
Maaaring hatiin sa 7 magkahiwalay na pagsubok, ang bawat isa ay magiging responsable para sa sarili nitong kaso ng pagsubok. Sa paglunsad nito, makikita natin na ito ay berde, iyon ay, matagumpay. Well, parang iyon lang. Bagama't maghintay, sinabi namin sa itaas na ang pamamaraang ito ay magiging mas mabilis replaceAllkaysa sa String. Well, tingnan natin:

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);
Susunod, ang code na ito ay pinatakbo ng tatlong beses at nakuha namin ang mga sumusunod na resulta: Console output:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
Tulad ng nakikita natin, sa karaniwan ang ating pamamaraan ay 5 beses na mas produktibo kaysa sa klasikong replaceAllklase ! StringWell, sa wakas, patakbuhin natin ang parehong tseke, ngunit, wika nga, walang kabuluhan. Sa madaling salita, sa kaso kapag walang nakitang tugma. Palitan natin ang string ng paghahanap mula "tyu"sa "--". Tatlong run ang nagbunga ng mga sumusunod na resulta: Console output:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
Sa karaniwan, tumaas ng 8.8 beses ang performance para sa mga kaso kung saan walang nakitang tugma! Palitan ang string sa Java - 4
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION