أفضل طريقة لاستبدال جميع العلامات في السلسلة بـ Java

StackOverflow https://stackoverflow.com/questions/816722

سؤال

لدي طريقة خدمة تأخذ سلسلة ثم تستبدل العلامات الموجودة في السلسلة بعناصر من مكتبة العلامات.على النحو التالي:

for( MetaDataDTO tag : tagValues )
{
    message = message.replace( tag.getKey(), tag.getText1() );
}

بوضوح؛يؤدي هذا إلى إنشاء أكوام من السلاسل الجديدة وهو أمر سيئ.لكن طريقة استبدال StringBuilder مرهقة للاستخدام مع سلاسل متعددة داخل سلسلة واحدة.كيف يمكنني أن أجعل طريقتي أكثر كفاءة؟

يتم استخدامه مع كتل نصية مثل:

عزيزي #الاسم_الأول#، طلبك الخاص بـ #applicationType# تمت الموافقة عليه ورفضه# آسف.

حيث #firstName# وما إلى ذلك هي المفاتيح الموجودة في قاعدة بيانات التعريف.من الممكن أيضًا ألا تكون العلامات محاطة بأحرف التجزئة.

هل كانت مفيدة؟

المحلول 2

وشكرا لشباب مساعدتكم. تعلمت بالتأكيد أكثر حول جافا. وإنني هنا الحل. هذا هو وسيلة لدعم علامات أبحث مختلفة، والعلامات ضمن علامات:

private static String replaceAllTags(String message, Map< String, String > tags)
{
    StringBuilder sb = new StringBuilder( message );
    boolean tagFound = false;
    /**
     * prevent endless circular text replacement loops
     */
    long recurrancyChecker = 5000;

    do
    {
        tagFound = false;
        Iterator it = tags.entrySet().iterator();
        while( it.hasNext() )
        {
            Map.Entry pairs = (Map.Entry) it.next();

            int start = sb.indexOf( pairs.getKey().toString() );

            while( start > -1 && --recurrancyChecker > 0 )
            {
                int length = pairs.getKey().toString().length();
                sb.replace( start, start + length, pairs.getValue().toString() );
                start = sb.indexOf( pairs.getKey().toString() );
                tagFound = true;
            }
        }
    }
    while( tagFound && --recurrancyChecker > 0 );
    return sb.toString();
}

نصائح أخرى

في الأساس تريد نسخ تنفيذ Matcher.replaceAll() مثل ذلك:

public static String replaceTags(String message, Map<String, String> tags) {
  Pattern p = Pattern.compile("#(\\w+)#");
  Matcher m = p.matcher(message);
  boolean result = m.find();
  if (result) {
    StringBuffer sb = new StringBuffer();
    do {
      m.appendReplacement(sb, tags.containsKey(m.group(1) ? tags.get(m.group(1)) : "");
      result = m.find();
    } while (result);
    m.appendTail(sb);
    message = sb.toString();
  }
  return message;
}

ملحوظة: لقد قمت بافتراض حول العلامة الصالحة (أي \w في التعبير العادي).سوف تحتاج إلى تلبية هذا لما هو صالح حقًا (على سبيل المثال "#([\w_]+)#").

لقد افترضت أيضًا أن العلامات أعلاه تبدو كالتالي:

Map<String, String> tags = new HashMap<String, String>();
tags.add("firstName", "Skippy");

و لا:

tags.add("#firstName#", "Skippy");

إذا كان الخيار الثاني صحيحًا، فستحتاج إلى التعديل وفقًا لذلك.

تقوم هذه الطريقة بإجراء تمريرة واحدة بالضبط عبر سلسلة الرسالة، لذا فهي لا تصبح أكثر كفاءة من هذا.

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