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

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

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


当前回答

截至2022年,最新的解决方案是Apache Commons Text StringSubstitutor

医生说:

// Build map
 Map<String, String> valuesMap = new HashMap<>();
 valuesMap.put("animal", "quick brown fox");
 valuesMap.put("target", "lazy dog");
 String templateString = "The ${animal} jumped over the ${target} ${undefined.number:-1234567890} times.";

 // Build StringSubstitutor
 StringSubstitutor sub = new StringSubstitutor(valuesMap);

 // Replace
 String resolvedString = sub.replace(templateString)

;

其他回答

jakarta commons lang的StrSubstitutor是一种轻量级的实现方法,前提是您的值已经被正确格式化。

http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/text/StrSubstitutor.html

Map<String, String> values = new HashMap<String, String>();
values.put("value", x);
values.put("column", y);
StrSubstitutor sub = new StrSubstitutor(values, "%(", ")");
String result = sub.replace("There's an incorrect value '%(value)' in column # %(column)");

上述结果为:

“第2列中的“1”值不正确”

当使用Maven时,您可以将此依赖项添加到pom.xml:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>

另一个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.

有Java插件使用字符串插值在Java(像在Kotlin, JavaScript)。支持Java 8,9,10,11…https://github.com/antkorwin/better-strings

在字符串字面量中使用变量:

int a = 3;
int b = 4;
System.out.println("${a} + ${b} = ${a+b}");

使用表达式:

int a = 3;
int b = 4;
System.out.println("pow = ${a * a}");
System.out.println("flag = ${a > b ? true : false}");

使用功能:

@Test
void functionCall() {
    System.out.println("fact(5) = ${factorial(5)}");
}

long factorial(int n) {
    long fact = 1;
    for (int i = 2; i <= n; i++) {
        fact = fact * i;
    }
    return fact;
}

更多信息,请阅读项目README。

我试了一下

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;
}
public static String format(String format, Map<String, Object> values) {
    StringBuilder formatter = new StringBuilder(format);
    List<Object> valueList = new ArrayList<Object>();

    Matcher matcher = Pattern.compile("\\$\\{(\\w+)}").matcher(format);

    while (matcher.find()) {
        String key = matcher.group(1);

        String formatKey = String.format("${%s}", key);
        int index = formatter.indexOf(formatKey);

        if (index != -1) {
            formatter.replace(index, index + formatKey.length(), "%s");
            valueList.add(values.get(key));
        }
    }

    return String.format(formatter.toString(), valueList.toArray());
}

例子:

String format = "My name is ${1}. ${0} ${1}.";

Map<String, Object> values = new HashMap<String, Object>();
values.put("0", "James");
values.put("1", "Bond");

System.out.println(format(format, values)); // My name is Bond. James Bond.