JavaRush /Java блогы /Random-KK /Java тіліндегі жолды ауыстырыңыз

Java тіліндегі жолды ауыстырыңыз

Топта жарияланған
Бағдарламалаушының жұмысында кейбір тапсырмалар немесе олардың құрамдас бөліктері жиі қайталануы мүмкін. Сондықтан бүгін мен кез келген Java әзірлеушісінің күнделікті жұмысында жиі кездесетін тақырыпқа тоқталғым келеді. Java-дағы жолды ауыстырыңыз - 1Белгілі бір әдістен белгілі бір жолды алдыңыз делік. Мұның бәрі жақсы сияқты, бірақ сізге сәйкес келмейтін кішкентай нәрсе бар. Мысалы, сепаратор жарамсыз және сізге басқа біреу қажет (немесе мүлдем жоқ). Мұндай жағдайда не істеуге болады? replaceӘрине, сыныптың әдістерін қолданыңыз String.

Java жолын ауыстыру

Түр нысанында Stringауыстыру әдісінің төрт нұсқасы бар replace:
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
Бұл әдістердің барлығының мақсаты бір – жолдың бір бөлігін басқа жолмен ауыстыру. Оларды толығырақ қарастырайық. 1.replace(char, char) String replace(char oldChar, char newChar) - бірінші аргумент сипатының барлық кездесулерін oldCharекіншісімен ауыстырады - newChar. Бұл мысалда үтірді нүктелі үтірмен ауыстырамыз:
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Консоль шығысы:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Белгіленген таңбалар тізбегіне сәйкес келетін жолдың әрбір ішкі жолын ауыстыру таңбалар тізбегімен ауыстырады.
String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
Қорытынды:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) - Көрсетілген тұрақты өрнекке сәйкес келетін бірінші ішкі жолды ауыстыру жолымен ауыстырады. Жарамсыз тұрақты өрнекті пайдаланған кезде PatternSyntaxException ұстай аласыз (бұл жақсы нәрсе емес). Бұл мысалда чемпион роботтың атын ауыстырайық:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Консоль шығысы:
In JavaRush, Amigo the best, Diego is Java God
Көріп отырғанымыздай, «Диегоның» бірінші жазбасы ғана өзгерді, бірақ кейінгілері қалдырылды, яғни қозғалмай қалды. 4. replaceAll()Java тілінде String replaceAll(String regex, String replacement) – бұл әдіс жолдағы ішкі жолдың барлық қайталануларын regex-мен ауыстырады replacement. Бірінші аргумент ретінде тұрақты өрнекті қолдануға болады regex. Мысал ретінде алдыңғы ауыстыруды атаулармен, бірақ жаңа әдіспен орындауға тырысайық:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Консоль шығысы:
In JavaRush, Amigo the best, Amigo is Java God
Көріп отырғанымыздай, барлық белгілер толықтай қажеттімен ауыстырылды. Амиго риза болады деп ойлаймын =)

Тұрақты өрнектер

Жоғарыда тұрақты тіркесті пайдаланып ауыстыруға болатыны айтылды. Алдымен тұрақты тіркес дегеніміз не екенін өзіміз анықтап алайық? Тұрақты өрнектер – метатаңбаларды (қойылмалы таңбаларды) пайдалануға негізделген мәтіндегі ішкі жолдарды іздеуге және өңдеуге арналған ресми тіл. Қарапайым тілмен айтқанда, бұл іздеу ережесін анықтайтын таңбалар мен метатаңбалар үлгісі. Мысалы: \D- кез келген цифрлық емес таңбаны сипаттайтын шаблон; \d— ретінде де сипатталуы мүмкін кез келген сандық таңбаны анықтайды [0-9]; [a-zA-Z]— а-дан z-ге дейінгі латын әріптерін сипаттайтын үлгі, регистрді ескермейді; Қолданбаны replaceAllсынып әдісінде қарастырыңыз String:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("\\s[a-zA-Z]{5}\\s", " Amigo ");
System.out.println(value);
Консоль шығысы:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— бос орындармен қоршалған 5 латын таңбасынан тұратын сөзді сипаттайды. Сәйкесінше, бұл үлгі біз өткен жолға ауыстырылады.

Java regex ауыстыру

Негізінде Java тіліндегі тұрақты өрнектерді пайдалану үшін java.util.regex. Негізгі сыныптар:
  1. Pattern- тұрақты өрнектің құрастырылған нұсқасын беретін класс.
  2. Matcher— бұл класс үлгіні түсіндіреді және ол қабылдайтын жолда сәйкестіктерді анықтайды.
Әдетте, бұл екі сынып бірге жұмыс істейді. MatcherСонымен, біздің алдыңғы an objectіміз қандай болады, бірақ және көмегімен 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);
Біздің қорытындымыз бірдей болады:
In JavaRush, Amigo the best, Amigo is Java God
Тұрақты тіркестер туралы толығырақ осы мақаладан оқи аласыз .

Барлығын ауыстыруға балама

replaceӘдістері өте әсерлі екені даусыз , бірақ оның an object екенін, яғни оны жасағаннан кейін өзгертуге болмайтынын Stringескермеуге болмайды . Сондықтан, әдістер арқылы жолдың кейбір бөліктерін ауыстырған кезде , біз нысанды өзгертпейміз , бірақ әр уақытта қажетті мазмұнмен жаңасын жасаймыз. Бірақ жаңа нысанды жасау көп уақытты алады, солай емес пе? Әсіресе, сұрақ бір-екі зат емес, бірнеше жүздік, тіпті мыңдық деген кезде. Сіз балама нұсқалар туралы ойлана бастайсыз. Ал бізде қандай балама бар? Хм... Оның қасиетіне келгенде , сіз бірден баламаларды ойлайсыз, бірақ StringBuilder/StringBuffer емес . Естеріңізде болса, бұл сыныптар шын мәнінде ерекшеленбейді, тек олар көп ағынды ортада пайдалану үшін оңтайландырылған, сондықтан олар бір ағынды пайдалануда біршама жылдамырақ жұмыс істейді. Осыған сүйене отырып, біз бүгін қолданамыз Бұл сыныпта көптеген қызықты әдістер бар, бірақ қазір бізді қызықтырады . — бұл әдіс осы тізбектің ішкі жолындағы таңбаларды көрсетілген жолдағы таңбалармен ауыстырады. Ішкі жол көрсетілген басынан басталады және индекстің соңындағы таңбаға дейін немесе ондай таңба болмаса, тізбектің соңына дейін жалғасады. Мысал қарастырайық: StringimmutablereplaceStringJava-дағы жолды ауыстырыңыз - 2StringimmutableimmutableStringBufferStringBuilderStringBuilder.replaceStringBuilder replace(int start, int end, String str)-1
StringBuilder strBuilder = new StringBuilder("Java Rush");
strBuilder.replace(5, 9, "God");
System.out.println(strBuilder);
Қорытынды:
Java God
Көріп отырғаныңыздай, біз жолды жазғымыз келетін интервалды көрсетеміз және аралықтағы нәрсенің үстіне ішкі жолды жазамыз. Сонымен, анықтаманы пайдалана отырып, StringBuilderбіз әдістің аналогын қайта жасаймыз replaceall java. Ол қалай көрінеді:
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();
}
Бір қарағанда қорқынышты, бірақ аздап түсінгеннен кейін бәрі соншалықты күрделі және өте қисынды емес екенін түсінуге болады.Бізде үш дәлел бар:
  • str— кейбір ішкі жолдарды ауыстырғымыз келетін жол;
  • oldStr— біз ауыстыратын ішкі жолдардың көрінісі;
  • newStr- оны немен ауыстырамыз.
ifКіріс деректерді тексеру үшін бізге бірінші қажет, ал егер жол бос strболса oldStrнемесе жаңа ішкі жол newStrбұрынғыға тең болса oldStr, әдісті орындау мағынасыз болады. Сондықтан біз бастапқы жолды қайтарамыз - str. Әрі қарай, біз newStrоны тексереміз null, егер солай болса, біз оны бізге ыңғайлы бос жол пішіміне түрлендіреміз - "". Содан кейін бізге қажет айнымалылардың мәлімдемесі бар:
  • жолдың жалпы ұзындығы str;
  • ішкі жол ұзындығы oldStr;
  • StringBuilderортақ жолдан нысан .
Біз жалпы жолдың ұзындығына тең бірнеше рет орындалатын циклды бастаймыз (бірақ, бұл ешқашан болмайды). Класс әдісі арқылы StringBuilder- indexOf- бізді қызықтыратын ішкі жолдың бірінші пайда болу индексін табамыз. indexOfӨкінішке орай, мен оның тұрақты өрнектермен жұмыс істемейтінін атап өткім келеді , сондықтан біздің соңғы әдісіміз тек жолдардың пайда болуымен жұмыс істейді (( Егер бұл индекс -ге тең болса -1, онда ағымдағы нысанда бұл оқиғалардың қайталануы болмайды StringBuilder, сондықтан біз қызығушылықтың нәтижесімен әдістен шығамыз: ол біз қолданатын StringBuilderтүрлендірілетін біздің ішінде қамтылған.Егер біздің индекс циклдің бірінші итерациясында тең болса , онда ауыстыруды қажет ететін ішкі жол жалпы мәнде болмаған. бастапқыда жол.Сондықтан мұндай жағдайда біз жай ғана жалпы жолды қайтарамыз.Одан кейін бізде бар және жоғарыда сипатталған әдіс ауыстырылатын ішкі жолдың координаталарын көрсету үшін оқиғаның табылған индексін пайдалану үшін қолданылады.Бұл цикл орындалады. ауыстыруды қажет ететін ішкі жолдар қанша рет табылса, егер жол тек ауыстыруды қажет ететін таңбадан тұрса, онда тек осы жағдайда бізде цикл толығымен орындалады және нәтижені жолға түрлендіреміз . Біз бұл әдістің дұрыстығын тексеруіміз керек, солай ма? Әртүрлі жағдайларда әдіс жұмысын тексеретін тест жазайық: StringtoString-1replaceStringBuilderStringBuilder
@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, "");
}
7 жеке сынаққа бөлуге болады, олардың әрқайсысы өз сынақ жағдайына жауап береді. Оны іске қосқаннан кейін оның жасыл, яғни сәтті екенін көреміз. Жарайды, бәрі осы сияқты. replaceAllКүте тұрсақ та, біз жоғарыда бұл әдіс -ге қарағанда жылдамырақ болатынын айттық String. Ал, қарастырайық:
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);
Содан кейін бұл code үш рет іске қосылды және біз келесі нәтижелерді алдық: Консоль шығысы:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
Көріп отырғанымыздай, біздің әдіс классикалық replaceAllклассқа қарағанда орташа есеппен String5 есе өнімді! Ақырында, сол тексеруді жүргізейік, бірақ, былайша айтқанда, бекер. Басқаша айтқанда, сәйкестік табылмаған жағдайда. "tyu"Іздеу жолын -дан бастап ауыстырайық "--". Үш жүгіру келесі нәтижелерді берді: Консоль шығысы:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
Орташа алғанда, сәйкестік табылмаған жағдайлардың өнімділігі 8,8 есе өсті! Java-дағы жолды ауыстырыңыз - 4
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION