在Java中使用string串联使用String.format是否更好?
在Java中使用String.Format
和string连接之间有明显的区别吗?
我倾向于使用String.format
但偶尔会滑和使用concat。 我在想,如果一个人比另一个人好。
我看到它的方式, String.Format
在“格式化”string给你更多的权力; 而连接意味着你不必担心无意中将额外的%s或丢失了一个。
String.format
也更短。
哪一个更可读取决于你的头像是如何工作的。
我build议最好使用String.format()
。 主要原因是String.format()
可以通过从资源文件中加载的文本更容易地进行本地化,但是如果不为每种语言生成不同代码的新可执行文件,则不能进行本地化。
如果您计划将您的应用程序设置为可本地化,则还应该养成为您的格式标记指定参数位置的习惯:
"Hello %1$s the time is %2$t"
然后可以对其进行本地化,并且交换名称和时间标记,而不需要重新编译可执行文件来说明不同的sorting。 使用参数位置,您也可以重复使用相同的参数,而不必将其传递给函数两次:
String.format("Hello %1$s, your name is %1$s and the time is %2$t", name, time)
关于performance:
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快得多。
既然有关于性能的讨论,我想我会添加一个包含StringBuilder的比较。 它实际上比concat更快,自然也是String.format选项。
为了使这种苹果苹果比较我实例化一个新的StringBuilder在循环而不是外部(这实际上比只做一个实例更快可能是由于重新分配空间的循环追加开销一个build造者)。
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] – Format = 1416毫秒
- 2012-01-11 16:30:46,190信息[TestMain] – Concatenation = 134毫秒
- 2012-01-11 16:30:46,313信息[TestMain] – string生成器= 117毫秒
.format
一个问题是你失去了静态types的安全性。 你的格式的参数可能太less,而且格式说明符的types可能是错误的,这两种格式IllegalFormatException
在运行时导致IllegalFormatException
,所以最终可能会logging破坏生产的代码。
相反, +
的参数可以由编译器testing。
哪一个更可读取决于你的头像是如何工作的。
你在那里得到了你的答案。
这是个人品味的问题。
string连接速度稍微快一点,但我认为这应该可以忽略不计。
以毫秒为单位的多个样本大小的testing。
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<iterations; 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<iterations; 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<iterations; 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
在StringBuilder上调用toString()方法的修改方法与上面相同。 下面的结果显示StringBuilder方法比使用+运算符的string串联慢了一点。
文件: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命令:(编译并运行5次StringTest)
> 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
String.format()
不仅仅是连接string。 例如,您可以使用String.format()
在特定语言环境中显示数字。
但是,如果您不关心本地化,则没有function差异。 也许一个比另一个更快,但在大多数情况下,它可以忽略不计。
我没有做任何具体的基准testing,但是我认为连接可能会更快。 String.format()创build一个新的Formatter,然后创build一个新的StringBuilder(大小只有16个字符)。 这是一个相当大的开销,尤其是如果你格式化一个更长的string和StringBuilder不断调整。
但是,连接不太有用,难于阅读。 与往常一样,值得在你的代码上做一个基准来看看哪个更好。 在您的资源包,语言环境等被加载到内存中并且代码被打印之后,服务器应用程序中的差异可能会被忽略。
也许作为一个最好的做法,创build一个适当大小的StringBuilder(Appendable)和Locale的自己的Formatter是一个好主意,如果你有很多的格式化的话可以使用它。
通常,string连接应优先于String.format
。 后者有两个主要的缺点:
- 它不编码以本地方式构build的string。
- 构build过程以string编码。
通过点1,我的意思是不可能了解一个String.format()
调用正在做一个单一的顺序传递。 一个被迫在格式string和参数之间来回移动,同时计算参数的位置。 对于简短的连接,这不是一个问题。 但是,在这些情况下,string连接不够冗长。
到了第二点,我的意思是构build过程的重要部分以格式string编码(使用DSL)。 使用string来表示代码有许多缺点。 它本质上不是types安全的,并且使语法高亮,代码分析,优化等复杂化。
当然,当使用Java语言之外的工具或框架时,新的因素可以发挥作用。
可能有一个明显的差异。
String.format
相当复杂,在下面使用正则expression式,所以不要把它当作在任何地方使用它的习惯,而只是在你需要它的地方。
StringBuilder
会更快一个数量级(正如某人已经指出的那样)。
上面的程序不能比较string串联和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") ; }
您会惊讶地发现格式在这里工作得更快。 这是因为创build的初始对象可能不会被释放,并且内存分配和性能可能会有问题。