Strsubstitutor замена библиотек JRE
на данный момент я использую org.apache.commons.lang.text.StrSubstitutor
для этого:
Map m = ...
substitutor = new StrSubstitutor(m);
result = substitutor.replace(input);
учитывая тот факт, что я хочу удалить commons-lang
зависимость от моего проекта, что было бы рабочей и минималистичной реализацией StrSubstitutor
использование стандартных библиотек JRE?
Примечание:
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}.");
уступая resolvedString = "быстрая коричневая лиса перепрыгнула через ленивую собаку."
2 ответов
если производительность не является приоритетом, можно использовать appendReplacement
метод Matcher
класс:
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();
}
это примерно 2x так же быстро, как версия regex и 3X быстрее, чем версия Apache commons В соответствии с моими тестами. Таким образом, обычный материал regex на самом деле более оптимизирован, чем версия apache. Обычно, конечно, не стоит. Просто для удовольствия, дайте мне знать, если вы можете сделать его более оптимизированным.
редактировать: как указывает @kmek, есть оговорка. Версия Apache будет разрешаться транзитивно. е.G, Если ${animal}
карты ${dog}
и dog
карты Golden Retriever
, версия apache будет отображать ${animal}
Золотой ретривер. Как я уже сказал, Вы должны использовать библиотеки, насколько это возможно. Вышеуказанное решение должно использоваться только в том случае, если у вас есть специальное ограничение, которое не позволяет использовать библиотеку.
нет ничего подобного, что я знаю в 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 все время