JavaRush /Java Blogu /Random-AZ /Java-da sətri dəyişdirin

Java-da sətri dəyişdirin

Qrupda dərc edilmişdir
Proqramçı işində çox vaxt bəzi tapşırıqlar və ya onların komponentləri təkrarlana bilər. Buna görə də bu gün hər hansı bir Java tərtibatçısının gündəlik işində tez-tez rast gəlinən bir mövzuya toxunmaq istərdim. Java-da sətri dəyişdirin - 1Tutaq ki, müəyyən bir metoddan müəyyən bir sətir alırsınız. Və bununla bağlı hər şey yaxşı görünür, amma sizə yaraşmayan kiçik bir şey var. Məsələn, ayırıcı uyğun deyil və başqasına ehtiyacınız var (və ya ümumiyyətlə yox). Belə bir vəziyyətdə nə etmək olar? replaceTəbii ki, sinfin metodlarından istifadə edin String.

Java sətirinin dəyişdirilməsi

Tip obyekti Stringdəyişdirmə metodunun dörd variantına malikdir replace:
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
Bütün bu üsulların məqsədi eynidir - sətirin bir hissəsini başqa bir sətirlə əvəz etmək. Gəlin onlara daha yaxından nəzər salaq. 1.replace(char, char) String replace(char oldChar, char newChar) - birinci arqumentin xarakterinin bütün baş vermələrini oldCharikinci ilə əvəz edir - newChar. Bu nümunədə vergülü nöqtəli vergüllə əvəz edəcəyik:
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Konsol çıxışı:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Müəyyən edilmiş simvol ardıcıllığına uyğun gələn sətirin hər bir alt sətirini əvəzedici simvollar ardıcıllığı ilə əvəz edir.
String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
Nəticə:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) - Göstərilən müntəzəm ifadəyə uyğun gələn birinci alt sətri əvəzedici sətirlə əvəz edir. Etibarsız normal ifadədən istifadə edərkən, siz PatternSyntaxException tuta bilərsiniz (bu yaxşı bir şey deyil). Bu nümunədə çempion robotun adını əvəz edək:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Konsol çıxışı:
In JavaRush, Amigo the best, Diego is Java God
Gördüyümüz kimi, "Dieqo"nun yalnız ilk girişi dəyişdi, lakin sonrakılar kənarda qaldı, yəni toxunulmaz. 4. replaceAll()Java-da String replaceAll(String regex, String replacement) - bu üsul sətirdəki alt sətirin bütün baş vermələrini regexilə əvəz edir replacement. Normal ifadə birinci arqument kimi istifadə edilə bilər regex. Nümunə olaraq, əvvəlki dəyişdirməni adlarla yerinə yetirməyə çalışaq, lakin yeni bir üsulla:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Konsol çıxışı:
In JavaRush, Amigo the best, Amigo is Java God
Gördüyümüz kimi, bütün simvollar tamamilə zəruri olanlarla əvəz edilmişdir. Məncə Amigo məmnun olacaq =)

Adi ifadələr

Yuxarıda deyildi ki, müntəzəm ifadədən istifadə etməklə əvəz etmək olar. Əvvəlcə özümüz aydınlaşdıraq ki, müntəzəm ifadə nədir? Müntəzəm ifadələr metasimvolların (wildcards) istifadəsinə əsaslanaraq mətndə alt sətirləri axtarmaq və manipulyasiya etmək üçün rəsmi dildir. Sadə dillə desək, bu, axtarış qaydasını təyin edən simvollar və metaxarakterlər nümunəsidir. Məsələn: \D- hər hansı qeyri-rəqəmsal simvolu təsvir edən şablon; \d— kimi də təsvir oluna bilən istənilən ədədi simvolu təyin edir [0-9]; [a-zA-Z]— a-dan z-ə qədər latın hərflərini təsvir edən şablon, hərflərə həssas olmayan; Tətbiqi replaceAllsinif metodunda nəzərdən keçirin 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 çıxışı:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— boşluqlarla əhatə olunmuş 5 latın hərfindən ibarət sözü təsvir edir. Müvafiq olaraq, bu şablon keçdiyimiz sətirlə əvəz olunur.

Java regex əvəz

Əsasən, Java-da müntəzəm ifadələrdən istifadə etmək üçün java.util.regex. Əsas siniflər bunlardır:
  1. Pattern- müntəzəm ifadənin tərtib edilmiş versiyasını təmin edən sinif.
  2. Matcher— bu sinif nümunəni şərh edir və qəbul etdiyi sətirdə uyğunluqları müəyyən edir.
Tipik olaraq, bu iki sinif birlikdə işləyir. MatcherBeləliklə, əvvəlki obyektimiz necə görünəcək, lakin və köməyi ilə 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);
Və nəticəmiz eyni olacaq:
In JavaRush, Amigo the best, Amigo is Java God
Bu məqalədə müntəzəm ifadələr haqqında daha çox oxuya bilərsiniz .

Bütün dəyişdirmək üçün alternativ

Şübhə yoxdur ki, üsullar çox təsir replaceedicidir , lakin onun bir obyekt olduğunu , yəni yaradılandan sonra dəyişdirilə bilməyəcəyini Stringnəzərdən qaçırmaq olmaz . Buna görə də, metodlardan istifadə edərək sətirin bəzi hissələrini əvəz etdikdə biz obyekti dəyişmirik , lakin hər dəfə lazımi məzmunla yenisini yaradırıq. Ancaq hər dəfə yeni bir obyekt yaratmaq çox vaxt aparır, elə deyilmi? Xüsusilə sual bir neçə obyekt deyil, bir neçə yüz, hətta minlərlə olduqda. İstər-istəməz, alternativlər haqqında düşünməyə başlayırsınız. Və hansı alternativlərimiz var? Hmm... Mülkiyyətinə gəldikdə , dərhal alternativləri düşünürsən, ancaq StringBuilder/StringBuffer deyil . Xatırladığımız kimi, bu siniflər əslində bir-birindən fərqlənmir, yalnız çox yivli mühitdə istifadə üçün optimallaşdırılmışdır, buna görə də tək yivli istifadədə bir qədər daha sürətli işləyirlər. Buna əsaslanaraq, bu gün istifadə edəcəyik Bu sinifdə bir çox maraqlı üsullar var, lakin konkret olaraq indi bizi maraqlandırır . — bu üsul bu ardıcıllığın alt sətirindəki simvolları göstərilən sətirdəki simvollarla əvəz edir. Alt sətir müəyyən edilmiş başlanğıcdan başlayır və indeksin sonundakı simvola qədər və ya belə simvol yoxdursa, ardıcıllığın sonuna qədər davam edir. Bir misala baxaq: StringimmutablereplaceStringJava-da sətri dəyişdirin - 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);
Nəticə:
Java God
Göründüyü kimi, sətri yazmaq istədiyimiz intervalı göstəririk və intervalda olanın üzərinə alt sətir yazırıq. Beləliklə, köməkdən istifadə edərək, StringBuildermetodun analoqunu yenidən yaradacağıq replaceall java. Necə görünəcək:
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();
}
İlk baxışdan qorxulu olsa da, bir az başa düşməklə hər şeyin o qədər də mürəkkəb və kifayət qədər məntiqli olmadığını başa düşə bilərsiniz.Üç arqumentimiz var:
  • str— bəzi alt sətirləri əvəz etmək istədiyimiz sətir;
  • oldStr— əvəz edəcəyimiz alt sətirlərin təsviri;
  • newStr- onu nə ilə əvəz edəcəyik.
ifGələn məlumatları yoxlamaq üçün bizə birinci lazımdır və sətir strya oldStrboşdursa, ya da yeni alt sətir newStrköhnəyə bərabərdirsə oldStr, metodun icrası mənasız olacaq. Buna görə də, orijinal sətri qaytarırıq - str. Sonra, yoxlayırıq və əgər newStrbelədirsə null, onu bizim üçün daha əlverişli olan boş sətir formatına çeviririk - "". Sonra bizə lazım olan dəyişənlərin bəyannaməsi var:
  • ümumi sim uzunluğu str;
  • alt sətir uzunluğu oldStr;
  • StringBuilderpaylaşılan sətirdən obyekt .
Biz ümumi sətir uzunluğuna bərabər bir neçə dəfə işləməli olan bir döngəyə başlayırıq (lakin, çox güman ki, bu heç vaxt baş verməyəcək). Sinif metodundan istifadə edərək StringBuilder- indexOf- bizi maraqlandıran alt sətirin ilk baş vermə indeksini tapırıq. Təəssüf ki, qeyd etmək istərdim ki, o, indexOfmüntəzəm ifadələrlə işləmir, ona görə də son metodumuz yalnız sətirlərin baş vermələri ilə işləyəcək (( bu indeks -ə bərabərdirsə -1, cari obyektdə daha bu hadisələrin təkrarlanması yoxdur StringBuilder, ona görə də biz maraq nəticəsi ilə metoddan çıxırıq: o , istifadə edərək StringBuilderçevirdiyimiz bizim daxilindədir.Əgər dövrənin birinci iterasiyasında indeksimiz bərabərdirsə , deməli dəyişdirilməli olan alt sətir ümumi deyildi. ilkin olaraq string.Ona görə də belə bir vəziyyətdə biz sadəcə olaraq ümumi sətri qaytarırıq.Sonra bizdə var və yuxarıda təsvir edilən üsul əvəz olunacaq alt sətirin koordinatlarını göstərmək üçün hadisənin tapılmış indeksindən istifadə etmək üçün istifadə olunur.Bu dövrə işləyəcək. dəyişdirilməsi lazım olan alt sətirlər nə qədər tapılırsa, əgər sətir yalnız dəyişdirilməsi lazım olan simvoldan ibarətdirsə, onda yalnız bu halda bizdə The loop tam işləyəcək və nəticənin sətirə çevrilməsini alacağıq . Bu metodun düzgünlüyünü yoxlamaq lazımdır, elə deyilmi? Müxtəlif vəziyyətlərdə metodun işini yoxlayan bir test yazaq: 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, "");
}
Hər biri öz test işinə cavabdeh olacaq 7 ayrı testə bölünə bilər. Onu işə saldıqdan sonra onun yaşıl olduğunu, yəni uğurlu olduğunu görəcəyik. Deyəsən hamısı budur. replaceAllBaxmayaraq ki, gözləyin, yuxarıda dedik ki, bu üsul -dan çox daha sürətli olacaq String. Yaxşı, gəlin nəzər salaq:
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);
Sonra, bu kod üç dəfə işlədilib və biz aşağıdakı nəticələri əldə etdik: Konsol çıxışı:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
Gördüyümüz kimi, orta hesabla bizim metodumuz klassik replaceAllsinifdən String5 dəfə daha məhsuldardır! Yaxşı, nəhayət, eyni yoxlamanı aparaq, amma belə demək mümkünsə, boş yerə. Başqa sözlə, uyğunluq tapılmadığı halda. "tyu"Axtarış sətirini ilə əvəz edək "--". Üç qaçış aşağıdakı nəticələri verdi: Konsol çıxışı:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
Heç bir uyğunluğun tapılmadığı hallar üzrə performans orta hesabla 8,8 dəfə artıb! Java-da sətri dəyişdirin - 4
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION