STROMELLEALLLLLLL ()
-
13-09-2019 - |
سؤال
سؤال بسيط جدا، ولكن هذا يأتي من شخص C / C ++ الدخول في تعقيدات Java.
أفهم أنني أستطيع إطلاق سراح Junit وبعض اختبارات الأداء الخاصة بي للحصول على إجابة؛ لكنني فقط أتساءل عما إذا كان هذا هناك.
هل هناك اختلاف (اختلاف) معروف بين string.replaceall () و matcher.replaceall () (على كائن matcher تم إنشاؤه من regex.pattern) من حيث الأداء؟
أيضا، ما هي اختلافات API 'API عالية المستوى بين كلاهما؟ (إمكانة، التعامل مع الخيال، التعامل مع السلاسل الفارغة، مما يجعل القهوة وما إلى ذلك)
المحلول
وفقا للوثائق ل String.replaceAll
, ، لديها ما يلي ليقوله حول استدعاء الطريقة:
استدعاء هذه الطريقة للنموذج
str.replaceAll(regex, repl)
غلة بالضبط نفس النتيجة مثل التعبيرPattern.compile(regex).matcher(str).replaceAll(repl)
لذلك، يمكن توقع ذلك الأداء بين الاحتجاج String.replaceAll
, ، وخلق صراحة Matcher
و Pattern
يجب أن يكون هو نفسه.
تعديل
كما تم الإشارة إليها في التعليقات، فإن اختلاف الأداء غير موجود سيكون صحيحا للحصول على مكالمة واحدة replaceAll
من عند String
أو Matcher
, ومع ذلك، إذا كان المرء يحتاج إلى إجراء مكالمات متعددة replaceAll
, ، يتوقع المرء أن تكون مفيدة للاحتفاظ بها Pattern
, ، لذلك لا يتعين تنفيذ مجموعة نمط التعبير العادي نسبيا في كل مرة.
نصائح أخرى
شفرة المصدر String.replaceAll()
:
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
يجب أن تجميع النمط أولا - إذا كنت ستشغيله عدة مرات بنفس النمط على الأوتار القصيرة، فسيكون الأداء أفضل بكثير إذا قمت بإعادة استخدام نمط واحد مترجم.
الفرق الرئيسي هو أنه إذا كنت تحمل Pattern
تستخدم لإنتاج Matcher
, ، يمكنك تجنب إعادة ترجمة Regex في كل مرة تستخدمها. يعبر من خلال String
, ، أنت لا تحصل على القدرة على "ذاكرة التخزين المؤقت" مثل هذا.
إذا كان لديك Regex مختلفة في كل مرة، باستخدام String
فئة replaceAll
على ما يرام. إذا كنت تطبق نفس Regex إلى العديد من السلاسل، فقم بإنشاء واحدة Pattern
وإعادة استخدامها.
غير قابل للتغيير / سلامة الخيط: أنماط مجمعة غير قابلة للتغيير، والمعاطفين ليست كذلك. (يرى هل Java Regex خيط آمن؟)
التعامل مع السلاسل الفارغة: يجب أن يتعامل RedurealLL مع سلاسل فارغة بأمان (لن تتطابق مع نمط سلسلة إدخال فارغة)
صنع القهوة، إلخ.: آخر ما سمعت، لا سلسلة ولا نمط ولا مانتر لديه أي ميزات API لذلك.
عدل
تنفيذ String.replaceAll
يخبرك بكل ما تحتاج إلى معرفته:
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
(ويقول المستندات نفس الشيء.)
بينما لم أفحصها للتخزين المؤقت، أود بالتأكيد تجميع نمط بمجرد والحفاظ على إشارة ثابتة إلى ذلك سيكون أكثر كفاءة من الاتصال Pattern.compile
مع نفس النمط في كل مرة. إذا كان هناك ذاكرة تخزين مؤقت، فسوف تكون إنقاذ كفاءة صغيرة - إذا لم يكن هناك واحدة كبيرة.
الفرق هو أن string.replaceall () يجمع Regex في كل مرة يطلق عليه. لا يوجد أي ما يعادلها لطريقة .NET Static Regex.Replace ()، والتي تخفف تلقائيا Regex المترجمة. عادة، resporkeall () هو شيء تفعله مرة واحدة فقط، ولكن إذا كنت ستدعوها مرارا وتكرارا بنفس regex، خاصة في حلقة، يجب عليك إنشاء كائن نمط واستخدام طريقة matcher.
يمكنك إنشاء Matcher في وقت مبكر، أيضا، واستخدم طريقة إعادة تعيين () ل RETARGET IT FET لكل استخدام:
Matcher m = Pattern.compile(regex).matcher("");
for (String s : targets)
{
System.out.println(m.reset(s).replaceAll(repl));
}
فائدة أداء إعادة استخدام Matcher، بالطبع، ليس هناك شيء كبير مثل إعادة استخدام النمط.
الإجابات الأخرى تغطي الجزء الكافي أداء جزء من البروتوكول الاختياري، ولكن فرق آخر بين Matcher::replaceAll
و String::replaceAll
هو أيضا سبب لتجميع خاصة بك Pattern
. وبعد عند ترجمة Pattern
نفسك، هناك خيارات مثل الأعلام لتعديل كيفية تطبيق Regex. علي سبيل المثال:
Pattern myPattern = Pattern.compile(myRegex, Pattern.CASE_INSENSITIVE);
ال Matcher
سوف يطبق جميع الأعلام التي قمت بتعيينها عند الاتصال Matcher::replaceAll
.
هناك أعلام أخرى يمكنك تعيينها كذلك. في الغالب أردت فقط أن أشير إلى أن Pattern
و Matcher
يحتوي API على الكثير من الخيارات، وهذا هو السبب الرئيسي لتجاوز البساطة String::replaceAll