目前我正在使用org.apache.commons.lang.text.StrSubstitutor
进行操作:
Map m = ...
substitutor = new StrSubstitutor(m);
result = substitutor.replace(input);
鉴于我想从我的项目中删除commons-lang
依赖项,使用标准JRE库的StrSubstitutor
的工作和简约实现是什么?
注意:
StrSubstitutor
的工作原理如下:
Map map = new HashMap();
map.put("animal", "quick brown fox");
map.put("target", "lazy dog");
StrSubstitutor sub = new StrSubstitutor(map);
String resolvedString = sub.replace("The ${animal} jumped over the ${target}.");
屈服于resolveString =“快速的棕色狐狸跳过懒狗。”
答案 0 :(得分:10)
如果性能不是优先事项,则可以使用appendReplacement
method of the Matcher
class:
public class StrSubstitutor {
private Map<String, String> map;
private static final Pattern p = Pattern.compile("\\$\\{(.+?)\\}");
public StrSubstitutor(Map<String, String> map) {
this.map = map;
}
public String replace(String str) {
Matcher m = p.matcher(str);
StringBuilder sb = new StringBuilder();
while (m.find()) {
String var = m.group(1);
String replacement = map.get(var);
m.appendReplacement(sb, replacement);
}
m.appendTail(sb);
return sb.toString();
}
}
性能更高但更丑陋的版本,只是为了好玩:)
public String replace(String str) {
StringBuilder sb = new StringBuilder();
char[] strArray = str.toCharArray();
int i = 0;
while (i < strArray.length - 1) {
if (strArray[i] == '$' && strArray[i + 1] == '{') {
i = i + 2;
int begin = i;
while (strArray[i] != '}') ++i;
sb.append(map.get(str.substring(begin, i++)));
} else {
sb.append(strArray[i]);
++i;
}
}
if (i < strArray.length) sb.append(strArray[i]);
return sb.toString();
}
根据我的测试,它大约是正则表达式版本的2倍,比apache commons版本快3倍。因此,正常的正则表达式实际上比apache版本更优化。当然通常不值得。只是为了好玩,让我知道你是否可以让它更加优化。
编辑:正如@kmek指出的那样,有一个警告。 Apache版本将过渡解决。例如,如果${animal}
映射到${dog}
而dog
映射到Golden Retriever
,则apache版本会将${animal}
映射到Golden Retriever。正如我所说,你应该尽可能使用库。如果您有一个不允许使用库的特殊约束,则仅使用上述解决方案。
答案 1 :(得分:1)
我在JRE中所知道的并不是这样,但写一个很简单。
Pattern p = Pattern.compile("${([a-zA-Z]+)}";
Matcher m = p.matcher(inputString);
int lastEnd = -1;
while (m.find(lastEnd+1)) {
int startIndex = m.start();
String varName = m.group(1);
//lookup value in map and substitute
inputString = inputString.substring(0,m.start())+replacement+inputString.substring(m.end());
lastEnt = m.start() + replacement.size();
}
这当然是非常低效的,您应该将结果写入StringBuilder而不是一直替换inputString