我需要专家建议以下方案。我有一个字符串模板(让我们假设电子邮件模板)如下。
Dear {PERSON_NAME},
We would like to thank you on behalf of {CEO_NAME}, {COMPANY_NAME}. You have been selected
for the position of {POSITION_NAME} in {DEPARTMENT_NAME}
etc etc
这是替换代码
String body = getTemplateBody(tempalteId);
sendMail(
body.replace("{PERSON_NAME}", personName )
.replace("{CEO_NAME}", ceoName),
.replace("{COMPANY_NAME}", companyName),
.replace("{POSITION_NAME}", positionName),
.replace("{DEPARTMENT_NAME}", deptName),
.replace("{X}", someVar1),
.replace("{Y}", someVar2),
.replace("{Z}", someVar3),
.replace("{ETC_ETC}", "etc")
);
我们拥有什么:
{PERSON_NAME}
问题:在模板字符串中替换变量以获取实际结果字符串的有效(非优雅)方法是什么
Efficient in terms of memory first and then processing
?
以上代码中是否有memory leakage
或any problem
?
请注意以上代码只是用简单的单词解释我的要求的示例,并且可能无法检查变量或方法名称编码标准。
答案 0 :(得分:1)
这里FreeMarker不是一个好选择吗?如果您使用FreeMarker,您可以在单独的模板文件中提供模板,并通过将模板与数据模型(bean或Map
)合并来构建输出。
// Setup config
Configuration cfg = new Configuration(Configuration.VERSION_2_3_21);
cfg.setDirectoryForTemplateLoading(new File("/where/you/store/templates"));
cfg.setDefaultEncoding("UTF-8");
// Create the data model - e.g. a bean or a map
final Map<String, String> root = new HashMap<>();
root.put("PERSON_NAME", "Joe");
root.put("CEO_NAME", "Anne");
// Get the template
Template temp = cfg.getTemplate("myTemplate.ftl");
// Merge the template with the data model
Writer out = new OutputStreamWriter(System.out);
temp.process(root, out);
答案 1 :(得分:0)
String::substring
方法实现如下:
return Pattern.compile(target.toString(), Pattern.LITERAL)
.matcher(this)
.replaceAll(Matcher.quoteReplacement(replacement.toString()));
使用上面的代码,您可以创建9个Pattern
和18
个中间String
。由于每个调用都会内联替换值,因此您不会遇到内存泄漏,尽管最终String
都会立即释放所有引用。
但是,您可以通过解析{
- }
封闭值的输入并使用String
组合最终StringBuilder
来更有效地实现此功能。这应该是你更关心的问题。
答案 2 :(得分:0)
如果您使用HashMap
作为替换持有者,则此解决方案具有线性运行时。
这个解决方案没什么特别的,只是简单的旧java;)
public static String format(CharSequence text, final Map<String, String> data)
{
if (text == null)
{
return "";
}
final int len = text.length();
if (len < 1)
{
return "";
}
final StringBuilder textSB = new StringBuilder();
final StringBuilder keySB = new StringBuilder();
int pos = 0;
boolean inKey = false;
char ch;
String value;
while (pos < len)
{
ch = text.charAt(pos);
if (ch == '{')
{
if (inKey)
{
throw new IllegalArgumentException("Invalid open key char at " + pos + 1);
}
inKey = true;
keySB.setLength(0);
}
else if (ch == '}')
{
if (!inKey)
{
throw new IllegalArgumentException("Invalid close key char at " + pos + 1);
}
inKey = false;
value = data.get(keySB.toString());
if (value == null)
{
throw new IllegalArgumentException("No value found for key " + keySB);
}
textSB.append(value);
}
else
{
if (inKey)
{
keySB.append(ch);
}
else
{
textSB.append(ch);
}
}
pos++;
}
if (inKey)
{
throw new IllegalArgumentException("None determined key detected.");
}
return textSB.toString();
}
答案 3 :(得分:-1)
这个怎么样?
使用带有密钥的HashMap
作为变量(即&#34; {PERSON_NAME}&#34;),并将该值作为此类密钥的相应获取者(即getPersonName()
)。显然,这个getter必须是Interface
。
恕我直言,这将是一个非常好的方式。
更有经验的人会怎么想?