使用JRE库替换StrSubstitutor [英] StrSubstitutor replacement with JRE libraries

查看:928
本文介绍了使用JRE库替换StrSubstitutor的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我正在使用 org.apache.commons.lang.text.StrSubstitutor 进行操作:

At the moment I am using org.apache.commons.lang.text.StrSubstitutor for doing:

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

result = substitutor.replace(input);

鉴于我想删除 commons-lang 依赖于我的项目使用标准JRE库的 StrSubstitutor 的工作和简约实现是什么?

Given the fact I want to remove commons-lang dependency from my project what would be a working and minimalistic implementation of StrSubstitutor using standard JRE libraries?

注意

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}.");

yielding resolvedString =快速的棕色狐狸跳过懒狗。

yielding resolvedString = "The quick brown fox jumped over the lazy dog."

推荐答案

如果性能不是优先级,则可以使用 appendReplacement 匹配器类的方法

If performance is not a priority, you can use the 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();
    }
}

性能更高但更丑陋的版本,只是为了好玩: )

A more performant but uglier version, just for fun :)

    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的速度快3倍根据我的测试版本。因此,正常的正则表达式实际上比apache版本更优化。当然通常不值得。只是为了好玩,让我知道你是否可以让它更优化。

It's about 2x as fast as the regex version and 3x faster than the apache commons version as per my tests. So the normal regex stuff is actually more optimized than the apache version. Usually not worth it of course. Just for fun though, let me know if you can make it more optimized.

编辑:正如@kmek指出的那样,有一个警告。 Apache版本将过渡解决。例如,如果 $ {animal} 映射到 $ {dog} dog 映射到 Golden Retriever ,apache版本会将 $ {animal} 映射到Golden Retriever。正如我所说,你应该尽可能使用库。如果您有一个不允许使用库的特殊约束,则仅使用上述解决方案。

Edit: As @kmek points out, there is a caveat. Apache version will resolve transitively. e.g, If ${animal} maps to ${dog} and dog maps to Golden Retriever, apache version will map ${animal} to Golden Retriever. As I said, you should use libraries as far as possible. The above solution is only to be used if you have a special constraint which does not allow you to use a library.

这篇关于使用JRE库替换StrSubstitutor的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆