سؤال

سؤال بسيط جدا، ولكن هذا يأتي من شخص 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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top