Apa pentingnya Pattern.compile()
metode?
Mengapa saya perlu mengkompilasi string regex sebelum mendapatkan Matcher
objek?
Sebagai contoh :
String regex = "((\\S+)\\s*some\\s*";
Pattern pattern = Pattern.compile(regex); // why do I need to compile
Matcher matcher = pattern.matcher(text);
new Pattern(regex)
daripada fungsi kompilasi statis. komentar marcolopes ada di tempat.Jawaban:
The
compile()
Metode selalu disebut di beberapa titik; itu satu-satunya cara untuk membuat objek Pola. Jadi pertanyaannya adalah, mengapa Anda harus menyebutnya secara eksplisit ? Salah satu alasannya adalah Anda memerlukan referensi ke objek Matcher sehingga Anda dapat menggunakan metodenya, sepertigroup(int)
mengambil konten dari grup penangkap. Satu-satunya cara untuk menguasai objek Matcher adalah melalui metode objek Patternmatcher()
, dan satu-satunya cara untuk menguasai objek Pattern adalah melaluicompile()
metode. Lalu adafind()
metode yang, tidak sepertimatches()
, tidak diduplikasi di kelas String atau Pola.Alasan lainnya adalah untuk menghindari membuat objek Pattern yang sama berulang kali. Setiap kali Anda menggunakan salah satu metode bertenaga regex dalam String (atau
matches()
metode statis dalam Pola), itu membuat Pola baru dan Pencocokan baru. Jadi cuplikan kode ini:... persis sama dengan ini:
Jelas, itu melakukan banyak pekerjaan yang tidak perlu. Faktanya, perlu waktu lebih lama untuk mengompilasi regex dan membuat instance objek Pattern dengan mudah, daripada melakukan pencocokan sebenarnya. Jadi biasanya masuk akal untuk menarik langkah itu keluar dari lingkaran. Anda juga dapat membuat Matcher sebelumnya, meskipun harganya tidak terlalu mahal:
Jika Anda terbiasa dengan regex .NET, Anda mungkin bertanya-tanya apakah
compile()
metode Java terkait denganRegexOptions.Compiled
pengubah .NET ; jawabannya adalah tidak.Pattern.compile()
Metode Java hanya setara dengan konstruktor Regex .NET. Saat Anda menentukanCompiled
opsi:... itu mengkompilasi regex langsung ke kode byte CIL, memungkinkannya untuk bekerja lebih cepat, tetapi dengan biaya yang signifikan dalam pemrosesan di muka dan penggunaan memori - anggap saja sebagai steroid untuk regex. Java tidak memiliki padanan; tidak ada perbedaan antara Pola yang dibuat di belakang layar oleh
String#matches(String)
dan yang Anda buat secara eksplisitPattern#compile(String)
.(EDIT: Awalnya saya mengatakan bahwa semua objek .NET Regex di-cache, yang tidak benar. Sejak .NET 2.0, cache otomatis hanya terjadi dengan metode statis seperti
Regex.Matches()
, bukan ketika Anda memanggil konstruktor Regex secara langsung. Ref )sumber
reset
menggunakan objek Matcher yang hanya digunakan oleh satu utas dalam satu waktu untuk mengurangi alokasi.Compile mengurai ekspresi reguler dan membuat representasi dalam memori . Overhead untuk dikompilasi signifikan dibandingkan dengan pertandingan. Jika Anda menggunakan pola berulang kali , akan ada beberapa performa untuk menyimpan pola yang dikompilasi ke dalam cache.
sumber
Ketika Anda mengkompilasi
Pattern
Java melakukan beberapa perhitungan untukString
mempercepat pencarian kecocokan . (Membangun representasi regex dalam memori)Jika Anda akan menggunakan kembali
Pattern
berkali-kali, Anda akan melihat peningkatan kinerja yang pesat dibandingkan membuat yang baruPattern
setiap saat.Dalam kasus hanya menggunakan Pola sekali, langkah kompilasi hanya tampak seperti baris kode tambahan, tetapi, pada kenyataannya, ini bisa sangat membantu dalam kasus umum.
sumber
Matcher matched = Pattern.compile(regex).matcher(text);
. Ada keuntungan dari hal ini dibandingkan dengan memperkenalkan satu metode: argumen diberi nama secara efektif dan jelas bagaimana memfaktorkan keluarPattern
untuk kinerja yang lebih baik (atau untuk membagi metode).Ini adalah masalah kinerja dan penggunaan memori, kompilasi dan pertahankan pola yang sesuai jika Anda perlu sering menggunakannya. Penggunaan regex yang khas adalah untuk memvalidasi input pengguna (format) , dan juga memformat data keluaran untuk pengguna , di kelas-kelas ini, menyimpan pola yang sesuai, tampaknya cukup logis karena biasanya disebut banyak.
Di bawah ini adalah contoh validator, yang disebut banyak :)
Seperti yang disebutkan oleh @Alan Moore, jika Anda memiliki regex yang dapat digunakan kembali dalam kode Anda, (sebelum loop misalnya), Anda harus mengkompilasi dan menyimpan pola untuk digunakan kembali.
sumber
Pattern.compile()
memungkinkan untuk menggunakan regex beberapa kali (ini aman untuk thread). Manfaat kinerja bisa sangat signifikan.Saya melakukan patokan cepat:
compileOnce berada di antara 3x dan 4x lebih cepat . Saya rasa ini sangat tergantung pada regex itu sendiri, tetapi untuk regex yang sering digunakan, saya memilih
static Pattern pattern = Pattern.compile(...)
sumber
Mengompilasi regex sebelumnya akan meningkatkan kecepatan. Menggunakan kembali Matcher memberi Anda sedikit percepatan. Jika metode dipanggil sering mengatakan dipanggil dalam satu lingkaran, kinerja keseluruhan pasti akan naik.
sumber
Mirip dengan 'Pattern.compile' ada 'RECompiler.compile' [dari com.sun.org.apache.regexp.internal] di mana:
1. kode yang dikompilasi untuk pola [az] memiliki 'az' di dalamnya
2. kode yang dikompilasi untuk pola [0-9] memiliki '09' di dalamnya
3. kode kompilasi untuk pola [abc] memiliki 'aabbcc' di dalamnya.
Jadi kode yang dikompilasi adalah cara terbaik untuk menggeneralisasi banyak kasus. Jadi alih-alih memiliki situasi penanganan kode yang berbeda 1,2 dan 3. Masalahnya berkurang menjadi membandingkan dengan ascii elemen sekarang dan berikutnya dalam kode yang dikompilasi, karenanya berpasangan. Jadi
a. apapun dengan ascii antara a dan z adalah antara a dan z
b. apapun dengan ascii antara 'a dan a pasti' a '
sumber
Kelas pola adalah titik masuk mesin regex. Anda dapat menggunakannya melalui Pattern.matches () dan Pattern.comiple (). #Perbedaan antara keduanya. match () - untuk memeriksa dengan cepat apakah teks (String) cocok dengan ekspresi reguler comiple () - buat referensi Pola. Jadi bisa menggunakan beberapa kali untuk mencocokkan ekspresi reguler dengan beberapa teks.
Sebagai referensi:
sumber