Các compile()
phương pháp được gọi là luôn luôn tại một số điểm; đó là cách duy nhất để tạo một đối tượng Pattern. Vì vậy, câu hỏi thực sự là, tại sao bạn nên gọi nó một cách rõ ràng ? Một lý do là bạn cần tham chiếu đến đối tượng Matcher để bạn có thể sử dụng các phương thức của nó, chẳng hạn như group(int)
lấy nội dung của các nhóm bắt. Cách duy nhất để có được đối tượng Matcher là thông qua matcher()
phương thức của đối tượng Pattern và cách duy nhất để có được đối tượng Pattern là thông qua compile()
phương thức. Sau đó, có find()
phương thức, không giống như matches()
, không bị trùng lặp trong các lớp Chuỗi hoặc Mẫu.
Lý do khác là tránh tạo lặp đi lặp lại cùng một đối tượng Pattern. Mỗi khi bạn sử dụng một trong các phương thức được hỗ trợ bởi regex trong Chuỗi (hoặc matches()
phương thức tĩnh trong Mẫu), nó sẽ tạo ra một Mẫu mới và một Matcher mới. Vì vậy, đoạn mã này:
for (String s : myStringList) {
if ( s.matches("\\d+") ) {
doSomething();
}
}
... chính xác tương đương với điều này:
for (String s : myStringList) {
if ( Pattern.compile("\\d+").matcher(s).matches() ) {
doSomething();
}
}
Rõ ràng, đó là làm rất nhiều công việc không cần thiết. Trên thực tế, có thể dễ dàng mất nhiều thời gian để biên dịch regex và khởi tạo đối tượng Pattern, hơn là thực hiện một khớp thực tế. Vì vậy, nó thường là hợp lý để kéo bước đó ra khỏi vòng lặp. Bạn cũng có thể tạo Matcher trước thời hạn, mặc dù chúng gần như không quá đắt:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("");
for (String s : myStringList) {
if ( m.reset(s).matches() ) {
doSomething();
}
}
Nếu bạn đã quen thuộc với .NET regexes, bạn có thể tự hỏi liệu compile()
phương thức của Java có liên quan đến công cụ RegexOptions.Compiled
sửa đổi của .NET hay không ; câu trả lời là không. Pattern.compile()
Phương thức của Java chỉ tương đương với phương thức khởi tạo Regex của .NET. Khi bạn chỉ định Compiled
tùy chọn:
Regex r = new Regex(@"\d+", RegexOptions.Compiled);
... nó biên dịch regex trực tiếp thành mã byte CIL, cho phép nó hoạt động nhanh hơn nhiều, nhưng với chi phí đáng kể trong xử lý phía trước và sử dụng bộ nhớ - hãy nghĩ về nó như steroid cho regex. Java không có tương đương; không có sự khác biệt giữa Mẫu được tạo đằng sau hậu trường String#matches(String)
và Mẫu do bạn tạo ra một cách rõ ràng Pattern#compile(String)
.
(CHỈNH SỬA: Ban đầu tôi đã nói rằng tất cả các đối tượng .NET Regex đều được lưu trong bộ nhớ cache, điều này không chính xác. Kể từ .NET 2.0, bộ nhớ đệm tự động chỉ xảy ra với các phương thức tĩnh như Regex.Matches()
, không phải khi bạn gọi trực tiếp một phương thức tạo Regex. Ref )