How to format strings in Java

Viewed 305821

Primitive question, but how do I format strings like this:

"Step {1} of {2}"

by substituting variables using Java? In C# it's easy.

10 Answers

String#format

The most frequent way to format a String is using this static method, that is long available since Java 5 and has two overloaded methods:

The method is easy to use and the format pattern is defined by underlying formatter.

String step1 = "one";
String step2 = "two";

// results in "Step one of two"
String string = String.format("Step %s of %s", step1, step2); 

You can pass a Locale to respect the language and regional specification. Refer to this answer for more information: https://stackoverflow.com/a/6431949/3764965 (credits to Martin Törnwall).

MessageFormat

The MessageFormat class is available since the first version of Java and is suitable for internationalization. In the simplest form, there is a static method for formatting:

String step1 = "one";
String step2 = "two";

// results in "Step one of two"
String string = MessageFormat.format("Step {0} of {1}", step1, step2);

Remember MessageFormat follows a specific pattern different from String#format, refer to its JavaDoc for more details: MessageFormat - patterns.

It is possible to use Locale, however, one has to instantiate the object of the class and pass it to the constructor since the static method above uses the default constructor with the default locale. Refer to this answer for more information: https://stackoverflow.com/a/6432100/3764965 (credits to ataylor).

Non standard JDK solutions

There are plenty of ways to format Strings using external libraries. They add little to no benefit if the libraries are imported solely for the purpose of String formatting. Few examples:

  • Apache Commons: StringSubstitutor, examples in its JavaDoc.
  • Cactoos: FormattedText, examples here.
  • Interestingly, Guava doesn't plan to add formatting or templating features: #1142.
  • ... and other custom implementations.

Feel free to add more, however, I find no reason to further expand this section.

Alternative since Java 15

There is a new instance method called String#formatted(Object... args) as of Java 15.

The internal implementation is the same as String#format(String format, Object... args).

Formats using this string as the format string, and the supplied arguments.

String step1 = "one";
String step2 = "two";

// results in "Step one of two"
String string = "Step %s of %s".formatted(step1, step2);     

Advantage: The difference is that the method is not static and the formatting pattern is a string itself from which a new one is created based on the args. This allows chaining to build the format itself first.

Disadvantage: There is no overloaded method with Locale, therefore uses the default one. If you need to use a custom Locale, you have to stick with String#format(Locale l, String format, Object... args).

This solution worked for me. I needed to create urls for a REST client dynamically so I created this method, so you just have to pass the restURL like this

/customer/{0}/user/{1}/order

and add as many params as you need:

public String createURL (String restURL, Object ... params) {       
    return new MessageFormat(restURL).format(params);
}

You just have to call this method like this:

createURL("/customer/{0}/user/{1}/order", 123, 321);

The output

"/customer/123/user/321/order"

I wrote this function it does just the right thing. Interpolate a word starting with $ with the value of the variable of the same name.

private static String interpol1(String x){
    Field[] ffield =  Main.class.getDeclaredFields();
    String[] test = x.split(" ") ;
    for (String v : test ) {
        for ( Field n: ffield ) {
            if(v.startsWith("$") && ( n.getName().equals(v.substring(1))  )){
                try {
                    x = x.replace("$" + v.substring(1), String.valueOf( n.get(null)));
                }catch (Exception e){
                    System.out.println("");
                }
            }
        }
    }
    return x;
}

Apache Commons StringSubstitutor provides a simple and readable way to do format Strings with named variables.

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."

This class supports providing default values for variables.

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

To use recursive variable replacement, call 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"

The org.apache.commons.text.StringSubstitutor helper class from Apache Commons Text provides named variable substitution

Map<String, String> valuesMap = new HashMap<>();
valuesMap.put("animal", "quick brown fox");
valuesMap.put("target", "lazy dog");
String resolved = new StringSubstitutor(valuesMap).replace("The ${animal} jumped over the ${target}.");
System.out.println(resolved); // The quick brown fox jumped over the lazy dog.
Related