当前位置: 首页 > 知识库问答 >
问题:

用JRE库替换strSubstantor

郭胤
2023-03-14

目前,我正在使用org.apache.commons.lang.text.strSubstantor执行以下操作:

Map m = ...
substitutor = new StrSubstitutor(m);

result = substitutor.replace(input);

如果我想从我的项目中移除commons-lang依赖项,那么使用标准JRE库的strSubstitutor的工作和最小化实现是什么呢?

注:

strSubstantor的工作方式如下:

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个答案

丌官运诚
2023-03-14

在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

连鸿
2023-03-14

<罢工> 如果性能不是优先级, 可以使用匹配器类的appendreplacement方法:

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();
    }

根据我的测试,它比regex版本快2倍,比apache commons版本快3倍。所以普通的正则表达式实际上比apache版本更优化。当然通常不值得。只是为了好玩,让我知道如果你可以使它更优化。

编辑:正如@kmek指出的,有一个警告。Apache版本将可传递地解析。例如,如果${animal}映射到${dog}并且dog映射到Golden Retriever,apache版本将把${animal}映射到Golden Retriever。正如我所说的,你应该尽可能地使用库。只有当您有一个不允许使用库的特殊约束时,才能使用上述解决方案。

 类似资料:
  • 问题内容: 目前,我正在这样做: 考虑到我想从项目中删除依赖的事实,使用标准JRE库将是一种可行且简单的实现方式吗? 注意事项 : 像这样工作: 产生resolveString =“快速的棕狐跳过了懒狗。 问题答案: 如果性能不是优先事项,则 可以使用类的方法: 一个更高性能但更丑陋的版本,只是为了好玩:) 根据我的测试,它大约是regex版本的2倍,比apache commons版本的3倍快。因

  • 正确的方法是什么?

  • 我有一个这样的清单: 在ansible playbook期间,库存只保存私有ip地址。我不想用公共ip替换的内容 注意,我不能使用模块,因为剧本在不同的阶段运行 有没有更好的方法做这件事?谢谢

  • 我的构建路径中有以下错误:将项目导入Eclipse后的JRE System Library[WebSphere v6.1 JRE](未绑定)。有人知道如何修复它吗?

  • 问题内容: 假设我的格式如下: 我想将小数点替换为空白,使其看起来像这样: 我该怎么做呢?我以为可以解决问题,但是当我尝试这样时: 我收到了一个错误消息,因为它可能不是字符。那是有道理的,那么我还能怎么完成我想要的? 问题答案: 如果您只是将单引号换成双引号,那么这将起作用,因为空字符串是合法值,而不是“空字符”,并且有重载。请记住,这是的超类型。

  • 问题内容: 我正在使用UpdatePanel在页面中异步调用按钮单击事件,该页面调用另一个类中的方法,该方法在输出中写出XML文件。有没有办法用JQuery而不是UpdatePanel做到这一点? 问题答案: 使用jQuery处理click事件。然后,使用此技术在后台代码中调用page方法。在这里,您可以编写XML文件或执行其他任何操作。