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. Tutaq 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?
replace
Təbii ki, sinfin metodlarından istifadə edin String
.
Java sətirinin dəyişdirilməsi
Tip obyektiString
dəyişdirmə metodunun dörd variantına malikdir replace
:
replace(char, char);
replace(CharSequence, CharSequence);
replaceFirst(String, String);
replaceAll(String, String).
replace(char, char)
String replace(char oldChar, char newChar)
- birinci arqumentin xarakterinin bütün baş vermələrini oldChar
ikinci 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 regex
ilə ə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 replaceAll
sinif 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 üçünjava.util.regex
. Əsas siniflər bunlardır:
Pattern
- müntəzəm ifadənin tərtib edilmiş versiyasını təmin edən sinif.Matcher
— bu sinif nümunəni şərh edir və qəbul etdiyi sətirdə uyğunluqları müəyyən edir.
Matcher
Belə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əsirreplace
edicidir , lakin onun bir obyekt olduğunu , yəni yaradılandan sonra dəyişdirilə bilməyəcəyini String
nə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: String
immutable
replace
String
String
immutable
immutable
StringBuffer
StringBuilder
StringBuilder.
replace
StringBuilder 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, StringBuilder
metodun 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.
if
Gələn məlumatları yoxlamaq üçün bizə birinci lazımdır və sətir str
ya oldStr
boşdursa, ya da yeni alt sətir newStr
kö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 newStr
belə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
; StringBuilder
paylaşılan sətirdən obyekt .
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, indexOf
mü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: String
toString
-1
replace
StringBuilder
StringBuilder
@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. replaceAll
Baxmayaraq 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 replaceAll
sinifdən String
5 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!
GO TO FULL VERSION