Katakanlah saya punya dua string,
String s1 = "AbBaCca";
String s2 = "bac";
Saya ingin melakukan cek kembali yang s2
ada di dalamnya s1
. Saya bisa melakukan ini dengan:
return s1.contains(s2);
Saya cukup yakin itu contains()
peka terhadap huruf besar-kecil, tetapi saya tidak bisa memastikan ini dengan membaca dokumentasi. Jika demikian maka saya kira metode terbaik saya akan menjadi sesuatu seperti:
return s1.toLowerCase().contains(s2.toLowerCase());
Selain itu, apakah ada cara lain (mungkin lebih baik) untuk mencapai hal ini tanpa memperhatikan sensitivitas huruf besar-kecil?
Jawaban:
Ya, berisi sensitif huruf. Anda dapat menggunakan java.util.regex.Pattern dengan flag CASE_INSENSITIVE untuk pencocokan case-sensitive:
EDIT: Jika s2 berisi karakter khusus regex (yang ada banyak) penting untuk mengutip terlebih dahulu. Saya sudah mengoreksi jawaban saya karena ini adalah yang pertama kali dilihat orang, tetapi pilih Matt Quail sejak dia menunjukkan ini.
sumber
Pattern.CASE_INSENSITIVE
, ini hanya berfungsi untuk karakter ASCII (yaitu, "Ä" tidak akan cocok dengan "ä"). Orang juga perlu menentukanUNICODE_CASE
bendera untuk mencapai itu.Pattern
lebih banyak pemain daripadas1.toLowerCase().contains(s2.toLowerCase())
?Pattern.compile(Pattern.quote(needle), Pattern.CASE_INSENSITIVE).matcher(haystack).find()
Satu masalah dengan jawaban oleh Dave L. adalah ketika s2 berisi markup regex seperti
\d
, dll.Anda ingin memanggil Pattern.quote () di s2:
sumber
toLowerCase().contains()
lebih cepat. Saya melakukan beberapa analisis kecepatan, lihat jawaban saya untuk hasil: stackoverflow.com/a/25379180/1705598Pattern.UNICODE_CASE
bendera juga. Bisakah Anda mengkonfirmasi ini?Kamu bisa menggunakan
The Apache Commons perpustakaan sangat berguna untuk hal semacam ini. Dan yang satu ini mungkin lebih baik daripada ekspresi reguler karena regex selalu mahal dalam hal kinerja.
sumber
String.regionMatches
, yang menggunakan konversi karakter-bijaksana, jadi tidak. Selain itu,containsIgnoreCase("ß", "ss")
mengembalikan -1, yang salah di setiap lokal ("s tajam" Jerman dikapitalisasi menjadi "ss".Implementasi Lebih Cepat: Memanfaatkan
String.regionMatches()
Menggunakan regexp bisa relatif lambat. Itu (lambat) tidak masalah jika Anda hanya ingin memeriksa dalam satu kasing. Tetapi jika Anda memiliki array atau koleksi ribuan atau ratusan ribu string, semuanya bisa menjadi sangat lambat.
Solusi yang disajikan di bawah ini tidak menggunakan ekspresi reguler atau
toLowerCase()
(yang juga lambat karena itu menciptakan string lain dan hanya membuangnya setelah cek).Solusinya dibangun di atas metode String.regionMatches () yang tampaknya tidak diketahui. Ia memeriksa apakah 2
String
wilayah cocok, tetapi yang penting adalah bahwa ia juga memiliki kelebihan denganignoreCase
parameter praktis .Analisis Kecepatan
Analisis kecepatan ini tidak berarti menjadi ilmu roket, hanya gambaran kasar tentang seberapa cepat berbagai metode tersebut.
Saya membandingkan 5 metode.
String.contains()
.String.contains()
dengan substring yang lebih dulu di-cache dan lebih rendah-huruf. Solusi ini sudah tidak sefleksibel karena menguji substring yang telah ditentukan sebelumnya.Pattern.compile().matcher().find()
...)Pattern
. Solusi ini sudah tidak sefleksibel karena menguji substring yang telah ditentukan.Hasil (dengan memanggil metode 10 juta kali):
Pattern
: 1845 msHasil dalam tabel:
Metode kami 4x lebih cepat dibandingkan dengan menggunakan dan menggunakan lebih rendah
contains()
, 10x lebih cepat dibandingkan dengan menggunakan ekspresi reguler dan juga 3x lebih cepat bahkan jikaPattern
pra-cache (dan kehilangan fleksibilitas memeriksa untuk substring sewenang-wenang).Kode Uji Analisis
Jika Anda tertarik bagaimana analisis dilakukan, berikut ini adalah aplikasi runnable yang lengkap:
sumber
ß
(S tajam Jerman;SS
huruf kapital ke ) dan juga untuk beberapa karakter lain (lihat sumberString.regionMatches
, yang mencoba kedua konversi).StringUtils.containsIgnoreCase()
adalah bahwa solusi saya dan Apache menggunakanregionMatches()
metode (dalam satu siklus), tetapi bahkan itu tidak sama dengan yang saya sebutString.regionMatches()
dan panggilan ApacheCharSequenceUtils.regionMatches()
.CharSequenceUtils.regionMatches
hanya meneleponString.regionMatches
sebenarnya. Ngomong-ngomong, maksud saya adalah untuk memberikan info, bahwa jika seseorang sudah menggunakan StringUtils lib dia bisa memanggilnya karena tampaknya cara yang efisien seperti Anda membuktikannya dengan tolok ukur Anda. Jika saya tidak menggunakan Apache lib, saya pasti akan menggunakan metode Anda;)Cara yang lebih sederhana untuk melakukan ini (tanpa khawatir tentang pencocokan pola) akan mengubah keduanya
String
menjadi huruf kecil:sumber
Ya, ini bisa dicapai:
Kode ini akan mengembalikan String "BENAR!" karena ditemukan bahwa karakter Anda mengandung.
sumber
s2
. Tidak berbicara tentang detail seperti itu yang ini tidak dikompilasi dan jika itu, itu akan mengembalikan string.Kamu bisa menggunakan ekspresi reguler , dan itu berfungsi:
sumber
Berikut ini beberapa yang ramah Unicode yang dapat Anda buat jika menarik ICU4j. Saya kira "abaikan kasus" dipertanyakan untuk nama metode karena meskipun perbandingan kekuatan utama mengabaikan kasus, itu digambarkan sebagai spesifik yang bergantung pada lokal. Tapi mudah-mudahan ini tergantung pada cara yang diharapkan pengguna.
sumber
Saya melakukan tes menemukan kecocokan case-string yang tidak sensitif. Saya memiliki 150.000 objek Vector semua dengan String sebagai satu bidang dan ingin menemukan bagian yang cocok dengan string. Saya mencoba tiga metode:
Konversi semua menjadi huruf kecil
Gunakan metode String cocok ()
Gunakan ekspresi reguler
Hasil pengaturan waktu adalah:
Tidak ada kecocokan yang dicoba: 20 msecs
Untuk menurunkan kecocokan: 182 msecs
Pencocokan string: 278 msecs
Ekspresi reguler: 65 msecs
Ekspresi reguler terlihat menjadi yang tercepat untuk use case ini.
sumber
Ada cara ringkas yang sederhana, menggunakan flag regex (case case {i}):
sumber
Saya tidak yakin apa pertanyaan utama Anda di sini, tapi ya, .contains peka huruf besar-kecil.
sumber
Pada dasarnya, ini adalah metode yang membutuhkan dua string. Seharusnya versi yang tidak sensitif case berisi (). Saat menggunakan metode berisi, Anda ingin melihat apakah satu string terkandung dalam yang lain.
Metode ini mengambil string yang "sub" dan memeriksa apakah itu sama dengan substring dari string kontainer yang panjangnya sama dengan "sub". Jika Anda melihat
for
loop, Anda akan melihat bahwa itu berulang di substring (yang merupakan panjang "sub") di atas string wadah.Setiap iterasi memeriksa untuk melihat apakah substring dari string kontainer
equalsIgnoreCase
ke sub.sumber
Jika Anda harus mencari string ASCII di string ASCII lain, seperti URL , Anda akan menemukan solusi saya menjadi lebih baik. Saya telah menguji metode icza dan menambang untuk kecepatan dan berikut hasilnya:
Kode:
sumber
sumber
sumber
Kita dapat menggunakan streaming dengan anyMatch dan berisi Java 8
sumber
atau Anda dapat menggunakan pendekatan sederhana dan hanya mengonversi kasus string ke kasus substring dan kemudian menggunakan metode berisi.
sumber
sumber
Anda bisa melakukan sesuatu seperti ini:
sumber