أفضل طريقة لاستبدال جميع العلامات في السلسلة بـ Java
-
03-07-2019 - |
سؤال
لدي طريقة خدمة تأخذ سلسلة ثم تستبدل العلامات الموجودة في السلسلة بعناصر من مكتبة العلامات.على النحو التالي:
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");
إذا كان الخيار الثاني صحيحًا، فستحتاج إلى التعديل وفقًا لذلك.
تقوم هذه الطريقة بإجراء تمريرة واحدة بالضبط عبر سلسلة الرسالة، لذا فهي لا تصبح أكثر كفاءة من هذا.