71

I'm looking for something to achieve the following:

String s = "hello {}!";
s = generate(s, new Object[]{ "world" });
assertEquals(s, "hello world!"); // should be true

I could write it myself, but It seems to me that I saw a library once which did this, probably it was the slf4j logger, but i don't want to write log messages. I just want to generate strings.

Do you know about a library which does this?

ndrizza
  • 3,145
  • 6
  • 25
  • 40
  • 4
    http://stackoverflow.com/questions/3695230/how-to-use-java-string-format – assylias Jun 28 '13 at 12:22
  • 1
    The slf4J uses `org.slf4j.helpers.MessageFormatter` The code looks like this: `String str = "Hello this is {} string {}"; MessageFormatter.format(str, new String[]{"hello", "world", "blah"}).getMessage();` – Himanshu Chaudhary Oct 05 '18 at 14:49

10 Answers10

87

See String.format method.

String s = "hello %s!";
s = String.format(s, "world");
assertEquals(s, "hello world!"); // should be true
Basil Bourque
  • 262,936
  • 84
  • 758
  • 1,028
Grzegorz Żur
  • 44,524
  • 14
  • 110
  • 102
  • 1
    how to replace two `String`s in the same `format()` ? example `String.format("%s %s!", ["hello", "world"]);` is this possible? – Carlos.V Jan 11 '19 at 18:02
  • 2
    @Carlos.V use `String.format("Hello %s welcome to %s!", "Carlos. V", "JAVA");` will print `Hello Carlos. V welcome to JAVA!` and you can use as many %s as you can. :) – AlokeT Aug 13 '19 at 06:05
37

StrSubstitutor from Apache Commons Lang may be used for string formatting with named placeholders:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.1</version>
</dependency>

https://commons.apache.org/proper/commons-lang/javadocs/api-3.4/org/apache/commons/lang3/text/StrSubstitutor.html :

Substitutes variables within a string by values.

This class takes a piece of text and substitutes all the variables within it. The default definition of a variable is ${variableName}. The prefix and suffix can be changed via constructors and set methods.

Variable values are typically resolved from a map, but could also be resolved from system properties, or by supplying a custom variable resolver.

Example:

String template = "Hi ${name}! Your number is ${number}";

Map<String, String> data = new HashMap<String, String>();
data.put("name", "John");
data.put("number", "1");

String formattedString = StrSubstitutor.replace(template, data);
Morgan Courbet
  • 546
  • 1
  • 6
  • 14
Justinas Jakavonis
  • 7,351
  • 6
  • 60
  • 98
  • 3
    The StrSubstitutor is deprecated, see [this SO post for a work around.](https://stackoverflow.com/questions/14044715/strsubstitutor-replacement-with-jre-libraries) – KeaganFouche Sep 20 '18 at 19:46
  • The `org.apache.commons.text.StringSubstitutor` from `org.apache.commons:commons-text:x.y` has taken it's place. Simply drop that one in and you're good to go without deprecation warnings. – andred Apr 29 '21 at 11:28
28

This can be done in a single line without the use of library. Please check java.text.MessageFormat class.

Example

String stringWithPlaceHolder = "test String with placeholders {0} {1} {2} {3}";
String formattedStrin = java.text.MessageFormat.format(stringWithPlaceHolder, "place-holder-1", "place-holder-2", "place-holder-3", "place-holder-4");

Output will be

test String with placeholders place-holder-1 place-holder-2 place-holder-3 place-holder-4
AbhishekB
  • 1,971
  • 3
  • 17
  • 23
  • 1
    This is the best solution when adding localization as the place holder order changes for different languages . – Manohar Oct 29 '20 at 12:28
11

If you can change the format of your placeholder, you could use String.format(). If not, you could also replace it as pre-processing.

String.format("hello %s!", "world");

More information in this other thread.

Community
  • 1
  • 1
LaurentG
  • 10,440
  • 8
  • 47
  • 64
9

There are two solutions:

Formatter is more recent even though it takes over printf() which is 40 years old...

Your placeholder as you currently define it is one MessageFormat can use, but why use an antique technique? ;) Use Formatter.

There is all the more reason to use Formatter that you don't need to escape single quotes! MessageFormat requires you to do so. Also, Formatter has a shortcut via String.format() to generate strings, and PrintWriters have .printf() (that includes System.out and System.err which are both PrintWriters by default)

fge
  • 114,841
  • 28
  • 237
  • 319
  • I remember reading/testing that MessageFormat was pretty slow. – assylias Jun 28 '13 at 12:24
  • 1
    @assylias meh, I don't know, my message bundle API proposes both since I have `ResourceBundle` compatibility... But I personally always use `Formatter`. – fge Jun 28 '13 at 12:25
  • 1
    I am not sure to be honest - and in most situations it won't make a difference anyway. – assylias Jun 28 '13 at 12:26
  • `MessageFormat` does have a few advantages over `Formatter` though, particularly the possibility to embed [`ChoiceFormat`](http://docs.oracle.com/javase/6/docs/api/java/text/ChoiceFormat.html) expressions. – gustafc Jun 28 '13 at 12:36
  • 1
    @gustafc not a problem, `Formatter` has [`Formattable`](http://docs.oracle.com/javase/7/docs/api/java/util/Formattable.html), which is even more powerful ;) – fge Jun 28 '13 at 12:40
  • @fge I wouldn't say that's a clearly better option in all circumstances, the canonical example being format strings like `Found {0,choice,0#nothing|1#one thing|{0} things}` – gustafc Jun 28 '13 at 13:06
6

You won't need a library; if you are using a recent version of Java, have a look at String.format:

String.format("Hello %s!", "world");
codebox
  • 19,161
  • 7
  • 57
  • 79
5

If you can tolerate a different kind of placeholder (i.e. %s in place of {}) you can use String.format method for that:

String s = "hello %s!";
s = String.format(s, "world" );
assertEquals(s, "hello world!"); // true
Sergey Kalinichenko
  • 697,062
  • 78
  • 1,055
  • 1,465
2

If you want to use some string to different placeholders, you could use pointers like this:

String.format("%1$s %2$s %1$s", "startAndEndText", "middleText");
MeLean
  • 2,183
  • 6
  • 25
  • 37
1

Justas answer is outdated so I'm posting up to date answer with apache text commons.

StringSubstitutor from Apache Commons Text may be used for string formatting with named placeholders: https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/StringSubstitutor.html

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.9</version>
</dependency>

This class takes a piece of text and substitutes all the variables within it. The default definition of a variable is ${variableName}. The prefix and suffix can be changed via constructors and set methods. Variable values are typically resolved from a map, but could also be resolved from system properties, or by supplying a custom variable resolver.

Example:

 // 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}.";

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

 // Replace
 String resolvedString = sub.replace(templateString);
Conrad
  • 417
  • 4
  • 11
0

The suggestion by https://stackoverflow.com/users/4290127/himanshu-chaudhary works quite well:

String str = "Hello this is {} string {}";     
str = MessageFormatter.format(str, "hello", "world").getMessage();
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.8.0-beta4</version>
</dependency>
Antoine
  • 899
  • 2
  • 15
  • 24
Rishi Raj
  • 3
  • 3