在Python中,格式化字符串时,我可以按名称而不是按位置填充占位符,如下所示:

print "There's an incorrect value '%(value)s' in column # %(column)d" % \
  { 'value': x, 'column': y }

我想知道这在Java中是否可能(希望没有外部库)?


当前回答

我试了一下

public static void main(String[] args) 
{
    String rowString = "replace the value ${var1} with ${var2}";
    
    Map<String,String> mappedValues = new HashMap<>();
    
    mappedValues.put("var1", "Value 1");
    mappedValues.put("var2", "Value 2");
    
    System.out.println(replaceOccurence(rowString, mappedValues));
}

private static  String replaceOccurence(String baseStr ,Map<String,String> mappedValues)
{
    for(String key :mappedValues.keySet())
    {
        baseStr = baseStr.replace("${"+key+"}", mappedValues.get(key));
    }
    
    return baseStr;
}

其他回答

可以使用Apache Commons StringSubstitutor。注意,StrSubstitutor已弃用。

import org.apache.commons.text.StringSubstitutor;
// ...
Map<String, String> values = new HashMap<>();
values.put("animal", "quick brown fox");
values.put("target", "lazy dog");
StringSubstitutor sub = new StringSubstitutor(values);
String result = sub.replace("The ${animal} jumped over the ${target}.");
// "The quick brown fox jumped over the lazy dog."

这个类支持为变量提供默认值。

String result = sub.replace("The number is ${undefined.property:-42}.");
// "The number is 42."

要使用递归变量替换,调用setEnableSubstitutionInVariables(true);。

Map<String, String> values = new HashMap<>();
values.put("b", "c");
values.put("ac", "Test");
StringSubstitutor sub = new StringSubstitutor(values);
sub.setEnableSubstitutionInVariables(true);
String result = sub.replace("${a${b}}");
// "Test"

我的答案是:

a)尽可能使用StringBuilder

b)保持“占位符”的位置(以任何形式:整数是最好的,特殊字符如dollar宏等),然后使用StringBuilder.insert()(参数的几个版本)。

当StringBuilder内部转换为String时,使用外部库似乎有些过度,而且我认为会显著降低性能。

另一个Apache Common StringSubstitutor的简单命名占位符的例子。

String template = "Welcome to {theWorld}. My name is {myName}.";

Map<String, String> values = new HashMap<>();
values.put("theWorld", "Stackoverflow");
values.put("myName", "Thanos");

String message = StringSubstitutor.replace(template, values, "{", "}");

System.out.println(message);

// Welcome to Stackoverflow. My name is Thanos.

试试Freemarker,模板库。

这是一个旧的线程,但只是为了记录,你也可以使用Java 8风格,像这样:

public static String replaceParams(Map<String, String> hashMap, String template) {
    return hashMap.entrySet().stream().reduce(template, (s, e) -> s.replace("%(" + e.getKey() + ")", e.getValue()),
            (s, s2) -> s);
}

用法:

public static void main(String[] args) {
    final HashMap<String, String> hashMap = new HashMap<String, String>() {
        {
            put("foo", "foo1");
            put("bar", "bar1");
            put("car", "BMW");
            put("truck", "MAN");
        }
    };
    String res = replaceParams(hashMap, "This is '%(foo)' and '%(foo)', but also '%(bar)' '%(bar)' indeed.");
    System.out.println(res);
    System.out.println(replaceParams(hashMap, "This is '%(car)' and '%(foo)', but also '%(bar)' '%(bar)' indeed."));
    System.out.println(replaceParams(hashMap, "This is '%(car)' and '%(truck)', but also '%(foo)' '%(bar)' + '%(truck)' indeed."));
}

输出将是:

This is 'foo1' and 'foo1', but also 'bar1' 'bar1' indeed.
This is 'BMW' and 'foo1', but also 'bar1' 'bar1' indeed.
This is 'BMW' and 'MAN', but also 'foo1' 'bar1' + 'MAN' indeed.