JavaRush /Java Blog /Random-ID /Ganti string di Java

Ganti string di Java

Dipublikasikan di grup Random-ID
Dalam pekerjaan seorang programmer, seringkali beberapa tugas atau komponennya diulangi. Oleh karena itu, hari ini saya ingin menyentuh topik yang sering ditemui dalam pekerjaan sehari-hari setiap pengembang Java. Ganti string di Java - 1Anggaplah Anda menerima string tertentu dari metode tertentu. Dan segala sesuatu tentangnya tampak baik-baik saja, tetapi ada beberapa hal kecil yang tidak cocok untuk Anda. Misalnya, pemisahnya tidak cocok, dan Anda memerlukan pemisah lain (atau tidak sama sekali). Apa yang bisa dilakukan dalam situasi seperti ini? Tentu saja, gunakan metode replacekelas String.

Penggantian string Java

Tipe objek Stringmemiliki empat variasi metode penggantian replace:
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
Tujuan dari semua metode ini adalah sama - mengganti bagian dari sebuah string dengan string lain. Mari kita lihat lebih dekat. 1.replace(char, char) String replace(char oldChar, char newChar) - menggantikan semua kemunculan karakter argumen pertama oldChardengan argumen kedua - newChar. Dalam contoh ini, kami akan mengganti koma dengan titik koma:
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Keluaran konsol:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Mengganti setiap substring dari string yang cocok dengan rangkaian karakter tertentu dengan rangkaian karakter pengganti.
String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
Kesimpulan:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) - Mengganti substring pertama yang cocok dengan ekspresi reguler yang ditentukan dengan string pengganti. Saat menggunakan ekspresi reguler yang tidak valid, Anda dapat menangkap PatternSyntaxException (yang bukan merupakan hal yang baik). Dalam contoh ini, mari kita ganti nama robot juara:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Keluaran konsol:
In JavaRush, Amigo the best, Diego is Java God
Seperti yang bisa kita lihat, hanya entri pertama “Diego” yang berubah, namun entri berikutnya tetap ditinggalkan—artinya, tidak tersentuh. 4. replaceAll()di Java String replaceAll(String regex, String replacement) - metode ini menggantikan semua kemunculan substring dalam string regexdengan replacement. Ekspresi reguler dapat digunakan sebagai argumen pertama regex. Sebagai contoh, mari kita coba melakukan penggantian sebelumnya dengan nama, tetapi dengan metode baru:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Keluaran konsol:
In JavaRush, Amigo the best, Amigo is Java God
Seperti yang bisa kita lihat, semua simbol telah diganti sepenuhnya dengan simbol yang diperlukan. Saya pikir Amigo akan senang =)

Ekspresi Reguler

Telah dikatakan di atas bahwa dimungkinkan untuk mengganti menggunakan ekspresi reguler. Pertama, mari kita perjelas sendiri apa itu ekspresi reguler? Ekspresi reguler adalah bahasa formal untuk mencari dan memanipulasi substring dalam teks, berdasarkan penggunaan metakarakter (wildcard). Sederhananya, ini adalah pola karakter dan metakarakter yang mendefinisikan aturan pencarian. Misalnya: \D- templat yang menjelaskan karakter non-digital apa pun; \d— mendefinisikan karakter numerik apa pun, yang juga dapat digambarkan sebagai [0-9]; [a-zA-Z]— templat yang mendeskripsikan karakter Latin dari a hingga z, tidak peka huruf besar/kecil; Pertimbangkan penerapan dalam metode replaceAllkelas String:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("\\s[a-zA-Z]{5}\\s", " Amigo ");
System.out.println(value);
Keluaran konsol:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— mendeskripsikan kata yang terdiri dari 5 karakter Latin yang dikelilingi spasi. Oleh karena itu, templat ini diganti dengan string yang kami lewati.

Penggantian regex Java

Pada dasarnya, untuk menggunakan ekspresi reguler di Java, kemampuan java.util.regex. Kelas-kelas utamanya adalah:
  1. Pattern- kelas yang menyediakan versi ekspresi reguler yang dikompilasi.
  2. Matcher— kelas ini menafsirkan pola dan menentukan kecocokan dalam string yang diterimanya.
Biasanya, kedua kelas ini bekerja bersamaan. Jadi, seperti apa objek kita sebelumnya, tapi dengan bantuan Matcherdan 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);
Dan kesimpulan kami akan sama:
In JavaRush, Amigo the best, Amigo is Java God
Anda dapat membaca lebih lanjut tentang ekspresi reguler di artikel ini .

Alternatif untuk menggantikanSemua

Tidak ada keraguan bahwa metodenya replacesangat Stringmengesankan, tetapi kita tidak dapat mengabaikan fakta bahwa Stringitu adalah immutablesebuah objek, yaitu, tidak dapat diubah setelah penciptaannya. Oleh karena itu, ketika kita mengganti beberapa bagian string menggunakan metode replace, kita tidak mengubah objeknya String, tetapi membuat objek baru setiap kali, dengan konten yang diperlukan. Tapi butuh waktu lama untuk membuat objek baru setiap saat, bukan? Apalagi yang ditanyakan bukan beberapa benda, melainkan beberapa ratus, bahkan ribuan. Mau tak mau, Anda mulai memikirkan alternatif lain. Dan alternatif apa yang kita punya? Ganti string di Java - 2Hmm... Kalau soal Stringpropertinya immutable, Anda langsung memikirkan alternatifnya, tapi tidak immutable, yaitu StringBuilder/StringBuffer . Seperti yang kita ingat, kelas-kelas ini sebenarnya tidak berbeda, kecuali bahwa StringBuffermereka dioptimalkan untuk digunakan dalam lingkungan multi-thread, sehingga StringBuildermereka bekerja lebih cepat dalam penggunaan single-thread. Berdasarkan hal ini, hari ini kita akan menggunakan StringBuilder. Kelas ini memiliki banyak metode menarik, tetapi secara khusus sekarang kita tertarik pada replace. StringBuilder replace(int start, int end, String str)— metode ini mengganti karakter dalam substring dari urutan ini dengan karakter dalam string yang ditentukan. Substring dimulai dari awal yang ditentukan dan berlanjut hingga karakter di akhir indeks, -1atau hingga akhir urutan jika tidak ada karakter tersebut. Mari kita lihat sebuah contoh:
StringBuilder strBuilder = new StringBuilder("Java Rush");
strBuilder.replace(5, 9, "God");
System.out.println(strBuilder);
Kesimpulan:
Java God
Seperti yang Anda lihat, kami menunjukkan interval di mana kami ingin menulis string, dan menulis substring di atas apa yang ada dalam interval tersebut. Jadi, dengan menggunakan bantuan tersebut, StringBuilderkami akan membuat ulang analog dari metode ini replaceall java. Bagaimana tampilannya:
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();
}
Sekilas memang menakutkan, tetapi dengan sedikit pemahaman Anda dapat memahami bahwa semuanya tidak begitu rumit dan cukup logis. Kami memiliki tiga argumen:
  • str— baris di mana kita ingin mengganti beberapa substring;
  • oldStr— representasi substring yang akan kami ganti;
  • newStr- dengan apa kami akan menggantinya.
ifKita memerlukan yang pertama untuk memeriksa data yang masuk, dan jika strstringnya oldStrkosong, atau substring baru newStrsama dengan yang lama oldStr, maka menjalankan metode ini tidak akan ada artinya. Oleh karena itu, kami mengembalikan string asli - str. Selanjutnya, kami memeriksa newStr, nulldan jika demikian, kami mengubahnya menjadi format string kosong yang lebih nyaman bagi kami - "". Kemudian kita mendeklarasikan variabel yang kita perlukan:
  • total panjang senar str;
  • panjang substring oldStr;
  • objek StringBuilderdari string bersama.
Kita memulai perulangan yang seharusnya berjalan beberapa kali sama dengan panjang total string (tetapi, kemungkinan besar, ini tidak akan pernah terjadi). Menggunakan metode kelas StringBuilder- indexOf- kita mengetahui indeks kemunculan pertama dari substring yang kita minati. Sayangnya, saya ingin mencatat bahwa ini indexOftidak berfungsi dengan ekspresi reguler, jadi metode terakhir kami hanya akan bekerja dengan kemunculan string (( Jika indeks ini sama dengan -1, maka tidak ada lagi kemunculan ini di objek saat ini StringBuilder, jadi kita keluar dari metode dengan hasil yang menarik: itu terkandung dalam StringBuilder, yang kita ubah menjadi String, menggunakan toStringJika indeks kita sama -1pada iterasi pertama dari loop, maka substring yang perlu diganti tidak ada pada umumnya string awalnya. Oleh karena itu, dalam situasi seperti ini, kita hanya mengembalikan string umum. Selanjutnya kita punya dan metode yang dijelaskan di atas digunakan replaceuntuk StringBuildermenggunakan indeks kejadian yang ditemukan untuk menunjukkan koordinat substring yang akan diganti. Loop ini akan berjalan sebanyak substring yang perlu diganti ditemukan. Jika string hanya terdiri dari karakter yang perlu diganti, maka hanya dalam kasus ini kita memiliki Perulangan akan berjalan sepenuhnya dan kita akan mendapatkan hasilnya StringBuilderdiubah menjadi string. Kita perlu memeriksa kebenaran metode ini, bukan? Mari kita menulis tes yang memeriksa pengoperasian metode dalam berbagai situasi:
@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, "");
}
Dapat dibagi menjadi 7 pengujian terpisah, yang masing-masing akan bertanggung jawab atas kasus pengujiannya sendiri. Setelah diluncurkan, kita akan melihatnya hijau, yaitu sukses. Yah, sepertinya itu saja. Meskipun tunggu, kami katakan di atas bahwa metode ini akan jauh lebih cepat replaceAlldaripada String. Baiklah, mari kita lihat:
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);
Selanjutnya, kode ini dijalankan tiga kali dan kami mendapatkan hasil sebagai berikut: Output konsol:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
Seperti yang bisa kita lihat, rata-rata metode kita 5 kali lebih produktif dibandingkan replaceAllkelas klasik! StringDan akhirnya, mari kita lakukan pemeriksaan yang sama, tetapi, bisa dikatakan, sia-sia. Dengan kata lain, jika tidak ditemukan kecocokan. Mari kita ganti string pencarian dari "tyu"menjadi "--". Tiga proses menghasilkan hasil sebagai berikut: Output konsol:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
Rata-rata, kinerja untuk kasus di mana tidak ditemukan kecocokan meningkat sebesar 8,8 kali lipat! Ganti string di Java - 4
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION