2011-11-25 26 views
5


Tôi tìm thấy điều này trong một số mã mà tôi muốn tối ưu hóa. Đây là snipet:Đó có phải là hành vi regex Java bình thường không?

tempString = bigBuffer.replaceAll("\\n", ""); 
tempString = tempString.replaceAll("\\t", ""); 

Sau đó, tôi quyết định sử dụng regex một cách khôn ngoan và tôi đã làm điều này:

tempString = bigBuffer.replaceAll("[\\n\\t]", ""); 

Sau đó, một người bạn nói với tôi để làm điều này thay vì:

tempString = bigBuffer.replaceAll("\\n|\\t", ""); 

Vì tôi muốn biết kết quả của những thay đổi của mình nên tôi đã làm một bài kiểm tra để xác minh xem đó có phải là một tối ưu hóa tốt hay không. Vì vậy, kết quả với (phiên bản java "1.6.0_27") là với mã đầu tiên là tham chiếu 100%.

Với đường ống là 121% nên mất nhiều thời gian hơn để thực hiện tác vụ.

Với khung hình vuông là 52% nên mất ít thời gian hơn để thực hiện tác vụ.

Tại sao regex lại hoạt động khác nhau khi nó giống nhau?

Martin

+0

Tại sao nó giống nhau? – BoltClock

+0

Tôi tin rằng nó sẽ giống nhau bởi vì nó làm điều tương tự. Có lẽ trình biên dịch cần tối ưu hóa khi đường ống được sử dụng với ký tự đơn. – Martin

Trả lời

4

Đoạn mã đầu tiên trông qua bigBuffer hai lần, lần đầu tiên thay thế các dây chuyền mới, và lần thứ hai thay thế các tab.

Đoạn mã thứ hai sẽ chỉ tìm kiếm qua bigBuffer một lần, kiểm tra xem từng ký tự là một hay cái kia. Điều này sẽ dẫn đến tốc độ kết thúc chỉ trong một nửa thời gian.

Đoạn mã ở vị trí thứ ba có thể được biên dịch kém và kết quả là phiên bản đặc biệt xấu của thuật toán mã đầu tiên, mặc dù tôi không thể chắc chắn mà không kiểm tra đường dẫn thông qua quá trình biên dịch regex.

Làm việc tuyệt vời trên thử nghiệm. Thời gian tương đối (dựa trên phần trăm) là hữu ích, thời gian tuyệt đối (mili giây hoặc một số như vậy) thì không.

2

Nói chung, một lớp nhân vật ([abc]) có xu hướng hiệu quả hơn so với thay đổi tương đương (a|b|c), vì vậy tôi không biết tại sao bạn của bạn đề xuất điều đó. Nhưng trong Java, các lớp ký tự chỉ khớp với các ký tự từ tiết mục Latin1 (tức là 256 điểm mã Unicode đầu tiên) được tối ưu hóa thêm. Đó có thể là lý do tại sao bạn thấy sự khác biệt lớn giữa kỹ thuật thứ hai và thứ ba.

Một lần nữa, đó chỉ là trong Java. Trong Perl, tôi cho rằng sự khác biệt giữa xen kẽ và lớp nhân vật là không đáng kể, nó là một sự triển khai trưởng thành hơn nhiều. Và trong grep, có lẽ sẽ rất khó để đo lường sự khác biệt bất kể phương pháp nào trong ba phương pháp bạn sử dụng - chỉ là nhanh thôi.

Nhưng theo quy tắc chung, nếu bạn có lựa chọn giữa việc sử dụng một lớp nhân vật hoặc một thay đổi, bạn nên chọn lớp nhân vật. Nó có thể không nhanh hơn, nhưng chắc chắn sẽ không chậm hơn. Và sử dụng không đúng cách, luân phiên có thể có ảnh hưởng tai hại đến hiệu suất.

+0

Cảm ơn các quy tắc của ngón tay cái, tôi sẽ chắc chắn rằng bạn của tôi biết về nó. – Martin

Các vấn đề liên quan