java 按位置格式化字符串_在Java中使用String.format而不是字符串连接是更好的做法吗?...

在Java中使用String.format而不是字符串连接是更好的做法吗?

在Java中使用String.format和字符串连接之间是否存在明显差异?

我倾向于使用String.format,但偶尔会滑倒并使用concat。 我想知道一个人是否比另一个好。

我看到它的方式,String.format给你更多的权力“格式化”字符串; 和连接意味着您不必担心意外地添加额外的%s或丢失一个%s。

String.format也更短。

哪一个更具可读性取决于你的头部如何工作。

12个解决方案

198 votes

我建议使用String.format()是更好的做法。主要原因是String.format()可以更容易地使用从资源文件加载的文本进行本地化,而连接无法在不生成每种语言的不同代码的新可执行文件的情况下进行本地化。

如果您计划将应用程序设置为可本地化,那么您还应养成为格式标记指定参数位置的习惯:

"Hello %1$s the time is %2$t"

然后可以对其进行本地化,并且可以交换名称和时间令牌,而无需重新编译可执行文件以考虑不同的顺序。 使用参数位置,您还可以重复使用相同的参数,而不将其传递给函数两次:

String.format("Hello %1$s, your name is %1$s and the time is %2$t", name, time)

workmad3 answered 2019-03-02T13:21:40Z

129 votes

关于表现:

public static void main(String[] args) throws Exception {

long start = System.currentTimeMillis();

for(int i = 0; i < 1000000; i++){

String s = "Hi " + i + "; Hi to you " + i*2;

}

long end = System.currentTimeMillis();

System.out.println("Concatenation = " + ((end - start)) + " millisecond") ;

start = System.currentTimeMillis();

for(int i = 0; i < 1000000; i++){

String s = String.format("Hi %s; Hi to you %s",i, + i*2);

}

end = System.currentTimeMillis();

System.out.println("Format = " + ((end - start)) + " millisecond");

}

时间结果如下:

连接= 265毫秒

格式= 4141毫秒

因此,连接比String.format快得多。

Icaro answered 2019-03-02T13:22:38Z

35 votes

由于有关性能的讨论,我想我会添加一个包含StringBuilder的比较。 它实际上比concat更快,自然是String.format选项。

为了使这成为一种苹果与苹果的比较,我在循环中而不是在外部实例化一个新的StringBuilder(这实际上比仅进行一次实例化更快,这很可能是由于在结束时为循环附加重新分配空间的开销。 一个建设者)。

String formatString = "Hi %s; Hi to you %s";

long start = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

String s = String.format(formatString, i, +i * 2);

}

long end = System.currentTimeMillis();

log.info("Format = " + ((end - start)) + " millisecond");

start = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

String s = "Hi " + i + "; Hi to you " + i * 2;

}

end = System.currentTimeMillis();

log.info("Concatenation = " + ((end - start)) + " millisecond");

start = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

StringBuilder bldString = new StringBuilder("Hi ");

bldString.append(i).append("; Hi to you ").append(i * 2);

}

end = System.currentTimeMillis();

log.info("String Builder = " + ((end - start)) + " millisecond");

2012-01-11 16:30:46,058 INFO [TestMain] - 格式= 1416毫秒

2012-01-11 16:30:46,190 INFO [TestMain] - 连接= 134毫秒

2012-01-11 16:30:46,313 INFO [TestMain] - String Builder = 117毫秒

TechTrip answered 2019-03-02T13:23:52Z

28 votes

+的一个问题是您失去了静态类型安全性。 您的格式参数太少,格式说明符可能有错误的类型 - 在运行时都会导致IllegalFormatException,因此最终可能会出现破坏生产的日志记录代码。

相反,+的参数可以由编译器测试。

Martin Schröder answered 2019-03-02T13:24:27Z

14 votes

哪一个更具可读性取决于你的头部如何工作。

你在那里得到了答案。

这是个人品味的问题。

我想,字符串连接速度稍快,但这应该可以忽略不计。

Thilo answered 2019-03-02T13:25:19Z

13 votes

这是一个测试,有多个样本大小,以毫秒为单位。

public class Time {

public static String sysFile = "/sys/class/camera/rear/rear_flash";

public static String cmdString = "echo %s > " + sysFile;

public static void main(String[] args) {

int i = 1;

for(int run=1; run <= 12; run++){

for(int test =1; test <= 2 ; test++){

System.out.println(

String.format("\nTEST: %s, RUN: %s, Iterations: %s",run,test,i));

test(run, i);

}

System.out.println("\n____________________________");

i = i*3;

}

}

public static void test(int run, int iterations){

long start = System.nanoTime();

for( int i=0;i

String s = "echo " + i + " > "+ sysFile;

}

long t = System.nanoTime() - start;

String r = String.format(" %-13s =%10d %s", "Concatenation",t,"nanosecond");

System.out.println(r) ;

start = System.nanoTime();

for( int i=0;i

String s = String.format(cmdString, i);

}

t = System.nanoTime() - start;

r = String.format(" %-13s =%10d %s", "Format",t,"nanosecond");

System.out.println(r);

start = System.nanoTime();

for( int i=0;i

StringBuilder b = new StringBuilder("echo ");

b.append(i).append(" > ").append(sysFile);

String s = b.toString();

}

t = System.nanoTime() - start;

r = String.format(" %-13s =%10d %s", "StringBuilder",t,"nanosecond");

System.out.println(r);

}

}

TEST: 1, RUN: 1, Iterations: 1

Concatenation = 14911 nanosecond

Format = 45026 nanosecond

StringBuilder = 3509 nanosecond

TEST: 1, RUN: 2, Iterations: 1

Concatenation = 3509 nanosecond

Format = 38594 nanosecond

StringBuilder = 3509 nanosecond

____________________________

TEST: 2, RUN: 1, Iterations: 3

Concatenation = 8479 nanosecond

Format = 94438 nanosecond

StringBuilder = 5263 nanosecond

TEST: 2, RUN: 2, Iterations: 3

Concatenation = 4970 nanosecond

Format = 92976 nanosecond

StringBuilder = 5848 nanosecond

____________________________

TEST: 3, RUN: 1, Iterations: 9

Concatenation = 11403 nanosecond

Format = 287115 nanosecond

StringBuilder = 14326 nanosecond

TEST: 3, RUN: 2, Iterations: 9

Concatenation = 12280 nanosecond

Format = 209051 nanosecond

StringBuilder = 11818 nanosecond

____________________________

TEST: 5, RUN: 1, Iterations: 81

Concatenation = 54383 nanosecond

Format = 1503113 nanosecond

StringBuilder = 40056 nanosecond

TEST: 5, RUN: 2, Iterations: 81

Concatenation = 44149 nanosecond

Format = 1264241 nanosecond

StringBuilder = 34208 nanosecond

____________________________

TEST: 6, RUN: 1, Iterations: 243

Concatenation = 76018 nanosecond

Format = 3210891 nanosecond

StringBuilder = 76603 nanosecond

TEST: 6, RUN: 2, Iterations: 243

Concatenation = 91222 nanosecond

Format = 2716773 nanosecond

StringBuilder = 73972 nanosecond

____________________________

TEST: 8, RUN: 1, Iterations: 2187

Concatenation = 527450 nanosecond

Format = 10291108 nanosecond

StringBuilder = 885027 nanosecond

TEST: 8, RUN: 2, Iterations: 2187

Concatenation = 526865 nanosecond

Format = 6294307 nanosecond

StringBuilder = 591773 nanosecond

____________________________

TEST: 10, RUN: 1, Iterations: 19683

Concatenation = 4592961 nanosecond

Format = 60114307 nanosecond

StringBuilder = 2129387 nanosecond

TEST: 10, RUN: 2, Iterations: 19683

Concatenation = 1850166 nanosecond

Format = 35940524 nanosecond

StringBuilder = 1885544 nanosecond

____________________________

TEST: 12, RUN: 1, Iterations: 177147

Concatenation = 26847286 nanosecond

Format = 126332877 nanosecond

StringBuilder = 17578914 nanosecond

TEST: 12, RUN: 2, Iterations: 177147

Concatenation = 24405056 nanosecond

Format = 129707207 nanosecond

StringBuilder = 12253840 nanosecond

Derek Ziemba answered 2019-03-02T13:25:55Z

9 votes

这是与上面相同的测试,修改了在StringBuilder上调用toString()方法。 下面的结果显示StringBuilder方法比使用+运算符的字符串连接稍慢。

file:StringTest.java

class StringTest {

public static void main(String[] args) {

String formatString = "Hi %s; Hi to you %s";

long start = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

String s = String.format(formatString, i, +i * 2);

}

long end = System.currentTimeMillis();

System.out.println("Format = " + ((end - start)) + " millisecond");

start = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

String s = "Hi " + i + "; Hi to you " + i * 2;

}

end = System.currentTimeMillis();

System.out.println("Concatenation = " + ((end - start)) + " millisecond");

start = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

StringBuilder bldString = new StringBuilder("Hi ");

bldString.append(i).append("Hi to you ").append(i * 2).toString();

}

end = System.currentTimeMillis();

System.out.println("String Builder = " + ((end - start)) + " millisecond");

}

}

Shell命令:(编译并运行StringTest 5次)

> javac StringTest.java

> sh -c "for i in \$(seq 1 5); do echo \"Run \${i}\"; java StringTest; done"

结果:

Run 1

Format = 1290 millisecond

Concatenation = 115 millisecond

String Builder = 130 millisecond

Run 2

Format = 1265 millisecond

Concatenation = 114 millisecond

String Builder = 126 millisecond

Run 3

Format = 1303 millisecond

Concatenation = 114 millisecond

String Builder = 127 millisecond

Run 4

Format = 1297 millisecond

Concatenation = 114 millisecond

String Builder = 127 millisecond

Run 5

Format = 1270 millisecond

Concatenation = 114 millisecond

String Builder = 126 millisecond

Akos Cz answered 2019-03-02T13:26:53Z

6 votes

String.format()不仅仅是串联字符串。 例如,您可以使用String.format()在特定区域设置中显示数字。

但是,如果您不关心本地化,则没有功能差异。也许一个比另一个快,但在大多数情况下它可以忽略不计......

Fortega answered 2019-03-02T13:27:31Z

2 votes

我没有做过任何具体的基准测试,但我认为连接可能会更快。 String.format()创建一个新的Formatter,然后创建一个新的StringBuilder(大小只有16个字符)。 这是一个相当大的开销,特别是如果你要格式化一个更长的字符串并且StringBuilder不断调整大小。

但是,连接不太有用且难以阅读。 与往常一样,值得对代码进行基准测试,看看哪个更好。 在资源包,区域设置等加载到内存中并且代码被JIT打开后,服务器应用程序中的差异可以忽略不计。

也许作为一种最佳实践,使用正确大小的StringBuilder(可附加)和Locale创建自己的Formatter是个好主意,如果你有很多格式要做,那就使用它。

AngerClown answered 2019-03-02T13:28:18Z

2 votes

可能存在明显的差异。

StringBuilder非常复杂并且在下面使用正则表达式,所以不要习惯在任何地方使用它,而只是在你需要它的地方。

StringBuilder会快一个数量级(正如这里有人已经指出的那样)。

Pawel Zieminski answered 2019-03-02T13:29:12Z

1 votes

通常,字符串连接应优先于String.format.后者有两个主要缺点:

它不对以本地方式构建的字符串进行编码。

构建过程以字符串形式编码。

从第1点开始,我的意思是无法理解String.format()呼叫在单个顺序传递中正在做什么。 一个人被迫在格式字符串和参数之间来回,同时计算参数的位置。 对于简短的连接,这不是一个问题。 但是,在这些情况下,字符串连接不那么冗长。

从第2点开始,我的意思是构建过程的重要部分是以格式字符串(使用DSL)编码的。 使用字符串来表示代码有许多缺点。 它本身并不是类型安全的,并且使语法突出显示,代码分析,优化等变得复杂。

当然,当使用Java语言外部的工具或框架时,新的因素可以发挥作用。

Stephane Bersier answered 2019-03-02T13:30:34Z

0 votes

您无法通过上面的程序比较String Concatenation和String.Format。

您可以尝试这样也可以在代码块中交换使用String.Format和Concatenation的位置,如下所示

public static void main(String[] args) throws Exception {

long start = System.currentTimeMillis();

for( int i=0;i<1000000; i++){

String s = String.format( "Hi %s; Hi to you %s",i, + i*2);

}

long end = System.currentTimeMillis();

System.out.println("Format = " + ((end - start)) + " millisecond");

start = System.currentTimeMillis();

for( int i=0;i<1000000; i++){

String s = "Hi " + i + "; Hi to you " + i*2;

}

end = System.currentTimeMillis();

System.out.println("Concatenation = " + ((end - start)) + " millisecond") ;

}

您会惊讶地发现Format在这里工作得更快。 这是因为创建的初始对象可能不会被释放,并且可能存在内存分配问题,从而导致性能问题。

DotNetUser answered 2019-03-02T13:31:25Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值