9

現在、私は次のこと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="速い茶色のキツネは怠惰な犬を飛び越えました。"

4

2 に答える 2

14

パフォーマンスが優先されない場合は、クラスの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();
    }

テストによると、正規表現バージョンの約 2 倍、Apache Commons バージョンの約 3 倍高速です。したがって、通常の正規表現は実際には apache バージョンよりも最適化されています。もちろん、通常はそれだけの価値はありません。楽しみのために、もっと最適化できるかどうか教えてください。

編集: @kmek が指摘しているように、注意点があります。Apache のバージョンは推移的に解決されます。たとえば、および に${animal}マップする場合、apache バージョンはGolden Retriever にマップされます。私が言ったように、可能な限りライブラリを使用する必要があります。上記の解決策は、ライブラリの使用を許可しない特別な制約がある場合にのみ使用してください。${dog}dogGolden Retriever${animal}

于 2012-12-26T19:47:35.853 に答える
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();
}

もちろん、これは恐ろしく非効率的であり、常に inputString を置き換えるのではなく、結果を StringBuilder に書き込む必要があります。

于 2012-12-26T18:49:39.000 に答える