目前我正在使用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 =“快速的棕色狐狸跳过懒狗.”
解决方法
如果性能不是优先级,则可以使用
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}并且狗映射到Golden Retriever,则apache版本会将${animal}映射到Golden Retriever.正如我所说,你应该尽可能使用库.如果您有一个不允许使用库的特殊约束,则仅使用上述解决方案.