JavaRush /Java blogi /Random-UZ /Java-da qatorni almashtiring

Java-da qatorni almashtiring

Guruhda nashr etilgan
Dasturchi ishida ko'pincha ba'zi vazifalar yoki ularning tarkibiy qismlari takrorlanishi mumkin. Shuning uchun, bugun men har qanday Java dasturchisining kundalik ishida tez-tez uchrab turadigan mavzuga to'xtalib o'tmoqchiman. Java-da qatorni almashtiring - 1Faraz qilaylik, siz ma'lum bir usuldan ma'lum bir qatorni olasiz. Va bu haqda hamma narsa yaxshi ko'rinadi, lekin sizga mos kelmaydigan kichik narsa bor. Masalan, ajratuvchi mos emas va sizga boshqasi kerak (yoki umuman yo'q). Bunday vaziyatda nima qilish mumkin? replaceTabiiyki, sinfning usullaridan foydalaning String.

Java satrini almashtirish

Tur ob'ekti Stringalmashtirish usulining to'rtta variantiga ega replace:
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
Ushbu usullarning barchasining maqsadi bir xil - satrning bir qismini boshqa satr bilan almashtirish. Keling, ularni batafsil ko'rib chiqaylik. 1.replace(char, char) String replace(char oldChar, char newChar) - birinchi argument xarakterining barcha hodisalarini oldCharikkinchisiga almashtiradi - newChar. Ushbu misolda vergulni nuqtali vergul bilan almashtiramiz:
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Konsol chiqishi:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Belgilangan belgilar ketma-ketligiga mos keladigan satrning har bir pastki qatorini almashtirish belgilar ketma-ketligi bilan almashtiradi.
String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
Xulosa:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) - Belgilangan muntazam ifodaga mos keladigan birinchi pastki qatorni almashtirish qatori bilan almashtiradi. Yaroqsiz muntazam ifodadan foydalanganda siz PatternSyntaxException ni qo'lga olishingiz mumkin (bu yaxshi narsa emas). Ushbu misolda chempion robot nomini almashtiramiz:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Konsol chiqishi:
In JavaRush, Amigo the best, Diego is Java God
Ko'rib turganimizdek, "Diego" ning faqat birinchi yozuvi o'zgargan, ammo keyingilari e'tibordan chetda qolgan, ya'ni tegmagan. 4. replaceAll()Java'da String replaceAll(String regex, String replacement) - bu usul qatordagi pastki qatorning barcha ko'rinishlarini regexbilan almashtiradi replacement. Birinchi argument sifatida muntazam ifodadan foydalanish mumkin regex. Misol tariqasida, oldingi almashtirishni nomlar bilan bajarishga harakat qilaylik, lekin yangi usul bilan:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Konsol chiqishi:
In JavaRush, Amigo the best, Amigo is Java God
Ko'rib turganimizdek, barcha belgilar to'liq keraklilari bilan almashtirildi. O'ylaymanki, Amigo xursand bo'ladi =)

Oddiy ifodalar

Muntazam ibora yordamida almashtirish mumkinligi yuqorida aytilgan edi. Avvalo, o'zimizga aniqlik kiritib olaylik, muntazam ibora nima? Muntazam iboralar metabelgilardan (joker belgilar) foydalanishga asoslangan matndagi pastki qatorlarni qidirish va manipulyatsiya qilish uchun rasmiy tildir. Oddiy qilib aytganda, bu qidiruv qoidasini belgilaydigan belgilar va meta-belgilar namunasidir. Masalan: \D- har qanday raqamli bo'lmagan belgini tavsiflovchi shablon; \d— har qanday raqamli belgini belgilaydi, uni quyidagicha ham tasvirlash mumkin [0-9]; [a-zA-Z]— a dan z gacha bo‘lgan lotin harflarini tavsiflovchi shablon, katta-kichik harflarni sezmaydi; Ilovani replaceAllsinf usulida ko'rib chiqing String:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("\\s[a-zA-Z]{5}\\s", " Amigo ");
System.out.println(value);
Konsol chiqishi:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— boʻshliqlar bilan oʻralgan 5 ta lotin harflaridan iborat soʻzni tasvirlaydi. Shunga ko'ra, ushbu shablon biz o'tkazgan satr bilan almashtiriladi.

Java regexni almashtirish

Asosan, Java-da muntazam ifodalardan foydalanish uchun java.util.regex. Asosiy sinflar quyidagilardir:
  1. Pattern- muntazam ifodaning kompilyatsiya qilingan versiyasini taqdim etadigan sinf.
  2. Matcher— bu sinf naqshni izohlaydi va qabul qilgan satrdagi mosliklarni aniqlaydi.
Odatda, bu ikki sinf birgalikda ishlaydi. MatcherShunday qilib, bizning oldingi ob'ektimiz qanday ko'rinishga ega bo'ladi, ammo va yordamida 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);
Va bizning xulosamiz bir xil bo'ladi:
In JavaRush, Amigo the best, Amigo is Java God
Muntazam iboralar haqida ko'proq ma'lumotni ushbu maqolada o'qishingiz mumkin .

replaceAll ga muqobil

replaceUsullar juda ta'sirli ekanligiga shubha yo'q , lekin uning ob'ekt ekanligini, ya'ni yaratilganidan keyin uni o'zgartirib bo'lmasligini Stringe'tiborsiz qoldirib bo'lmaydi . Shuning uchun, usullar yordamida satrning ba'zi qismlarini almashtirganimizda , biz ob'ektni o'zgartirmaymiz , balki har safar kerakli tarkibga ega yangisini yaratamiz. Lekin har safar yangi ob'ekt yaratish uzoq vaqt talab etadi, shunday emasmi? Ayniqsa, savol bir nechta ob'ektlar emas, balki bir necha yuzlab, hatto minglab bo'lsa. To'g'rirog'i, siz muqobil variantlar haqida o'ylay boshlaysiz. Va bizda qanday alternativalar bor? Hmm... Uning mulki haqida gap ketganda , siz darhol muqobil variantlar haqida o'ylaysiz, lekin StringBuilder/StringBuffer emas . Esda tutganimizdek, bu sinflar aslida bir-biridan farq qilmaydi, faqat ular ko'p tarmoqli muhitda foydalanish uchun optimallashtirilgan, shuning uchun ular bir torli foydalanishda biroz tezroq ishlaydi. Shunga asoslanib, bugun biz foydalanamiz Bu sinfda juda ko'p qiziqarli usullar mavjud, ammo biz hozir qiziqamiz . — bu usul ushbu ketma-ketlikning pastki qatoridagi belgilarni belgilangan qatordagi belgilar bilan almashtiradi. Pastki qator belgilangan boshidan boshlanadi va indeks oxiridagi belgigacha yoki bunday belgi mavjud bo'lmasa, ketma-ketlikning oxirigacha davom etadi. Keling, bir misolni ko'rib chiqaylik: StringimmutablereplaceStringJava-da satrni almashtiring - 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);
Xulosa:
Java God
Ko'rib turganingizdek, biz satrni yozmoqchi bo'lgan intervalni ko'rsatamiz va oraliqdagi narsaning ustiga pastki qatorni yozamiz. Shunday qilib, yordamdan foydalanib, StringBuilderbiz usulning analogini qayta yaratamiz replaceall java. Bu qanday ko'rinishga ega bo'ladi:
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();
}
Bir qarashda qo'rqinchli, ammo ozgina tushunsangiz, hamma narsa unchalik murakkab va mantiqiy emasligini tushunishingiz mumkin.Bizda uchta dalil bor:
  • str— biz ba'zi pastki qatorlarni almashtirmoqchi bo'lgan qator;
  • oldStr— biz almashtiradigan pastki satrlarni ko'rsatish;
  • newStr- uni nima bilan almashtiramiz.
ifBizga kiruvchi ma'lumotlarni tekshirish uchun birinchisi kerak va agar satr bo'sh strbo'lsa oldStryoki yangi pastki qator newStreskisiga teng bo'lsa oldStr, usulni bajarish ma'nosiz bo'ladi. Shuning uchun biz asl qatorni qaytaramiz - str. Keyinchalik, biz newStrni tekshiramiz nullva agar shunday bo'lsa, biz uni biz uchun qulayroq bo'lgan bo'sh string formatiga aylantiramiz - "". Keyin bizga kerak bo'lgan o'zgaruvchilar deklaratsiyasi mavjud:
  • umumiy ip uzunligi str;
  • pastki qator uzunligi oldStr;
  • StringBuilderumumiy satrdan ob'ekt .
Biz umumiy satr uzunligiga teng bo'lgan bir necha marta ishlashi kerak bo'lgan tsiklni boshlaymiz (lekin, ehtimol, bu hech qachon sodir bo'lmaydi). Sinf usulidan foydalanib StringBuilder- indexOf- bizni qiziqtirgan pastki qatorning birinchi paydo bo'lish indeksini topamiz. Afsuski, shuni ta'kidlashni istardimki, u indexOfoddiy iboralar bilan ishlamaydi, shuning uchun bizning yakuniy usulimiz faqat satrlarning paydo bo'lishi bilan ishlaydi (( Agar bu indeks ga teng bo'lsa -1, joriy ob'ektda bunday hodisalarning boshqa takrorlanishi yo'q StringBuilder, shuning uchun biz qiziqish natijasi bilan usuldan chiqamiz: u bizda mavjud bo'lib StringBuilder, biz ga aylantiramiz String, yordamida toString.. Agar tsiklning birinchi iteratsiyasida bizning indeksimiz teng bo'lsa -1, u holda almashtirilishi kerak bo'lgan pastki qator umumiy bo'lmagan. Dastlab string.Shuning uchun, bunday vaziyatda biz oddiygina umumiy satrni qaytaramiz.Keyingi bizda mavjud va yuqorida tavsiflangan usul o'zgartirilishi kerak bo'lgan pastki satrning koordinatalarini ko'rsatish uchun hodisaning topilgan indeksidan foydalanish replaceuchun ishlatiladi.Ushbu tsikl ishlaydi. StringBuilderqancha marta almashtirilishi kerak bo'lgan pastki satrlar topilgan bo'lsa, agar satr faqat almashtirilishi kerak bo'lgan belgidan iborat bo'lsa, unda faqat shu holatda bizda Loop to'liq ishlaydi va natijani satrga aylantiramiz StringBuilder. Ushbu usulning to'g'riligini tekshirishimiz kerak, to'g'rimi? Keling, turli vaziyatlarda usulning ishlashini tekshiradigan test yozamiz:
@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 ta alohida testga bo'linishi mumkin, ularning har biri o'z test ishi uchun javobgar bo'ladi. Uni ishga tushirib, biz uning yashil ekanligini, ya'ni muvaffaqiyatli ekanligini ko'ramiz. Xo'sh, hammasi shu kabi ko'rinadi. replaceAllKutishga qaramay, biz yuqorida bu usul ga qaraganda ancha tezroq bo'lishini aytdik String. Xo'sh, keling, bir ko'rib chiqaylik:
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);
Keyinchalik, ushbu kod uch marta ishga tushirildi va biz quyidagi natijalarga erishdik: Konsol chiqishi:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
Ko'rib turganimizdek, bizning usulimiz klassik replaceAllsinfga qaraganda o'rtacha String5 baravar samaraliroq! Xo'sh, nihoyat, xuddi shu tekshiruvni o'tkazaylik, lekin, aytganda, behuda. Boshqacha qilib aytganda, hech qanday moslik topilmagan holatda. "tyu"Qidiruv qatorini dan ga almashtiramiz "--". Uchta yugurish quyidagi natijalarni berdi: Konsol chiqishi:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
O'rtacha hisobda, mos keluvchi topilmagan holatlar bo'yicha ko'rsatkich 8,8 baravar oshdi! Java-da satrni almashtiring - 4
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION