How to format strings in Java
Solution 1
In addition to String.format, also take a look java.text.MessageFormat
. The format less terse and a bit closer to the C# example you've provided and you can use it for parsing as well.
For example:
int someNumber = 42;
String someString = "foobar";
Object[] args = {new Long(someNumber), someString};
MessageFormat fmt = new MessageFormat("String is \"{1}\", number is {0}.");
System.out.println(fmt.format(args));
A nicer example takes advantage of the varargs and autoboxing improvements in Java 1.5 and turns the above into a one-liner:
MessageFormat.format("String is \"{1}\", number is {0}.", 42, "foobar");
MessageFormat
is a little bit nicer for doing i18nized plurals with the choice modifier. To specify a message that correctly uses the singular form when a variable is 1 and plural otherwise, you can do something like this:
String formatString = "there were {0} {0,choice,0#objects|1#object|1<objects}";
MessageFormat fmt = new MessageFormat(formatString);
fmt.format(new Object[] { new Long(numberOfObjects) });
Solution 2
Take a look at String.format. Note, however, that it takes format specifiers similar to those of C's printf family of functions -- for example:
String.format("Hello %s, %d", "world", 42);
Would return "Hello world, 42". You may find this helpful when learning about the format specifiers. Andy Thomas-Cramer was kind enough to leave this link in a comment below, which appears to point to the official spec. The most commonly used ones are:
- %s - insert a string
- %d - insert a signed integer (decimal)
- %f - insert a real number, standard notation
This is radically different from C#, which uses positional references with an optional format specifier. That means that you can't do things like:
String.format("The {0} is repeated again: {0}", "word");
... without actually repeating the parameter passed to printf/format. (see The Scrum Meister's comment below)
If you just want to print the result directly, you may find System.out.printf (PrintStream.printf) to your liking.
Solution 3
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)
.
Solution 4
If you choose not to use String.format, the other option is the + binary operator
String str = "Step " + a + " of " + b;
This is the equivalent of
new StringBuilder("Step ").append(String.valueOf(1)).append(" of ").append(String.valueOf(2));
Whichever you use is your choice. StringBuilder is faster, but the speed difference is marginal. I prefer to use the +
operator (which does a StringBuilder.append(String.valueOf(X)))
and find it easier to read.
Solution 5
I've wrote my simple method for it :
public class SomeCommons {
/** Message Format like 'Some String {0} / {1}' with arguments */
public static String msgFormat(String s, Object... args) {
return new MessageFormat(s).format(args);
}
}
so you can use it as:
SomeCommons.msfgFormat("Step {1} of {2}", 1 , "two");
Related videos on Youtube
katit
Updated on December 07, 2021Comments
-
katit over 2 years
Primitive question, but how do I format strings like this:
"Step {1} of {2}"
by substituting variables using Java? In C# it's easy.
-
The Scrum Meister almost 13 yearsSee This Question
-
ℛɑƒæĿᴿᴹᴿ about 7 years
-
-
Andy Thomas almost 13 yearsAnother option is java.text.MessageFormat, which does accept the {1} style format symbols. String.format()'s format symbols can be similar to C's printf() format symbols -- but can also differ. See download.oracle.com/javase/6/docs/api/java/util/… for the full syntax.
-
The Scrum Meister almost 13 years
String.format
can also take numeric positions:String.format("%2$s %1$s", "foo", "bar");
will outputbar foo
-
Ryan Amos over 12 yearsIf you're going to neg rep me, please explain why.
-
Søren Løvborg over 11 years1) In response to a question on string formatting, you explain how the
+
operator works. 2) Your explanation isn't even accurate.+
is equivalent to usingStringBuilder
, notString.concat
. (Way too much info on this.) -
pavel_kazlou over 11 yearsMessageFormat is for localization purposes, so take care when using it. For example the following code
MessageFormat.format("Number {0}", 1234));
depending on default locale can produceNumber 1,234
instead ofNumber 1234
. -
user3145373 ツ over 9 years@ataylor : Hello, Sorry but I am little confused. I want to something like that I ll pass Class object that has data & when
{0} it ll take firstname
, when{1} then lastname
, like so. Is it possible like{0,choice,0.getFirstName()}
or something like that ? -
ataylor over 9 years@user3145373ツ I don't think so.
-
user3145373 ツ over 9 yearsOk fine, I have refer one .Net project like that I want, codeproject.com/Articles/42310/…, refer this project I am looking like this. If you know any project or packages available like that then please tell me. Thank you
-
ℛɑƒæĿᴿᴹᴿ about 7 yearsYou're right docs.oracle.com/javase/8/docs/api/java/util/…
-
ArtOfWarfare over 3 yearsNice! Too bad I'm still working with Java 8 right now. We're debating to move either to Java 11 or Java 14 in the next year or so... so we probably won't be able to use this feature for another 3-5 years.
-
Nikolas Charalambidis over 3 yearsI'd be more optimistic. The LTS version will be Java 17 as of September 2021 so this feature might get handy. I haven't noticed such structural changes like the modular system between the 8 and 9 versions so I believe the migration will be faster :))
-
Starney Binson over 2 yearsStarting from Java 15 it is possible to use String.format directly on the String using String.formatted().
"Hello %s, %d".formatted("world", 42)
-
ccpizza over 2 years❗️
MessageFormat
is orders of magnitude slower thanString.format
— avoid it unless you plan to live forever. This should NOT be the accepted answer.