在Python中,我们可以很容易地做到这一点:有没有办法在Java中呈现字符串'Hello,%(name)s'%{'name':'Felix'}?
data = {'name':'Felix'}
s = 'Hello, %(name)s' % data
s
'Hello, Felix'
有没有在Java中类似的方式来实现同样的事情?
PS: 对不清楚的问题。用例是:我们有一个存储键值的映射,模板只需要在映射中指定一个键,那么键的值将在模板中键的位置。
在Python中,我们可以很容易地做到这一点:有没有办法在Java中呈现字符串'Hello,%(name)s'%{'name':'Felix'}?
data = {'name':'Felix'}
s = 'Hello, %(name)s' % data
s
'Hello, Felix'
有没有在Java中类似的方式来实现同样的事情?
PS: 对不清楚的问题。用例是:我们有一个存储键值的映射,模板只需要在映射中指定一个键,那么键的值将在模板中键的位置。
在这种使用情况下,你需要一个模板引擎一样速度或freemarker的使用像地图的数据结构来呈现一个字符串模板,有没有在java中内置模块来做到这一点。像这样(速度):
public static void main(String[] args) {
Context context = new VelocityContext();
context.put("appid", "9876543d1");
context.put("ds", "2013-09-11");
StringWriter sw = new StringWriter();
String template = "APPID is ${appid} and DS is ${ds}";
Velocity.evaluate(context, sw, "velocity", template);
System.out.println(sw.toString());
}
据我所知,您可以使用String#format
此:
String name = "Felix";
String s = String.format("Hello, %s", name);
System.out.println(s);
这将打印有关如何使用的String#format
格式
Hello, Felix
更多信息可以在java.util.Formatter
syntax
你想找到String.format方法。
String data = "Hello, %s";
String updated = String.format(data, "Felix");
如果你想要一个像国际化支持更先进的技术,您可以使用先进的信息格式功能
例如: 在langage属性文件添加属性“模板”至极是你的信息
template = At {2,time,short} on {2,date,long}, \
we detected {1,number,integer} spaceships on \
the planet {0}.
那么你可以格式化你的valriables传递参数数组中的:
Object[] messageArguments = {
"Mars",
new Integer(7),
new Date()
};
您调用格式化这样说:
MessageFormat formatter = new MessageFormat("");
formatter.setLocale(currentLocale);
formatter.applyPattern(messages.getString("template"));
String output = formatter.format(messageArguments);
的具体例子是在这里 http://docs.oracle.com/javase/tutorial/i18n/format/messageFormat.html
如果你想只替换字符串字符串,然后从我的回答的第二部分的代码会更好
Java Formatter类不支持%(key)s
表单,但是可以使用%index$s
,其中索引从1开始计数,就像本例中一样
System.out.format("%3$s, %2$s, %1s", "a", "b", "c");
// indexes 1 2 3
输出:
c, b, a
因此,所有你需要做的是创造一些数组将包含在图案中使用的值,并因为通过使用第一更改索引键名到其对应的索引(增加1格式化程序编写为1$
而不是0$
,就像我们对数组索引所期望的那样)。
下面是示例方法的,会做它为您
// I made this Pattern static and put it outside of method to compile it only once,
// also it will match every (xxx) that has % before it, but wont include %
static Pattern formatPattern = Pattern.compile("(?<=%)\\(([^)]+)\\)");
public static String format(String pattern, Map<String, ?> map) {
StringBuffer sb = new StringBuffer();
List<Object> valuesList = new ArrayList<>();
Matcher m = formatPattern.matcher(pattern);
while (m.find()) {
String key = m.group(1);//group 1 contains part inside parenthesis
Object value = map.get(key);
// If map doesn't contain key, value will be null.
// If you want to react somehow to null value like throw some
// Exception
// now is the good time.
if (valuesList.contains(value)) {
m.appendReplacement(sb, (valuesList.indexOf(value) + 1) + "\\$");
} else {
valuesList.add(value);
m.appendReplacement(sb, valuesList.size() + "\\$");
}
}
m.appendTail(sb);
return String.format(sb.toString(), valuesList.toArray());
}
使用
Map<String, Object> map = new HashMap<>();
map.put("name", "Felix");
map.put("age", 70);
String myPattern =
"Hi %(emptyKey)s! My name is %(name)s %(name)s and I am %(age)s years old";
System.out.println(format(myPattern, map));
输出:
Hi null! My name is Felix Felix and I am 70 years old
正如你可以看到你可以使用相同的密钥几次(在我们的案例中为name
),并且如果您的地图不包含字符串模式中使用的密钥(如emptyKey
)将被替换为null
。
以上的版本,是为了让你设置数据的类型像s
d
等,但如果你的数据总是用绳子代替,那么你可以跳过String.format(sb.toString(), valuesList.toArray())
,并与以前的值替换所有你的钥匙。
下面是简化版本,将只接受地图<String,String>
键值关系。
static Pattern stringsPattern = Pattern.compile("%\\(([^)]+)\\)s\\b");
public static String formatStrings(String pattern, Map<String, String> map) {
StringBuffer sb = new StringBuffer();
Matcher m = stringsPattern.matcher(pattern);
while (m.find()) {
// we can't use null as replacement so we need to convert it to String
// first. We can do it with String.valueOf method
m.appendReplacement(sb, String.valueOf(map.get(m.group(1))));
}
m.appendTail(sb);
return sb.toString();
}