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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/925423/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:10:50  来源:igfitidea点击:

Is it better practice to use String.format over string Concatenation in Java?

javastringconcatenationstring.format

提问by Omar Kooheji

Is there a perceptible difference between using String.formatand String concatenation in Java?

String.format在 Java 中使用和字符串连接之间有明显的区别吗?

I tend to use String.formatbut occasionally will slip and use a concatenation. I was wondering if one was better than the other.

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

The way I see it, String.formatgives you more power in "formatting" the string; and concatenation means you don't have to worry about accidentally putting in an extra %s or missing one out.

在我看来,String.format在“格式化”字符串方面给了你更多的权力;和串联意味着您不必担心不小心添加了额外的 %s 或错过了一个。

String.formatis also shorter.

String.format也更短。

Which one is more readable depends on how your head works.

哪一个更具可读性取决于您的大脑如何工作。

采纳答案by workmad3

I'd suggest that it is better practice to use String.format(). The main reason is that String.format()can be more easily localised with text loaded from resource files whereas concatenation can't be localised without producing a new executable with different code for each language.

我建议最好使用String.format(). 主要原因是String.format()使用从资源文件加载的文本可以更轻松地本地化,而如果不为每种语言生成具有不同代码的新可执行文件,则无法本地化连接。

If you plan on your app being localisable you should also get into the habit of specifying argument positions for your format tokens as well:

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

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

This can then be localised and have the name and time tokens swapped without requiring a recompile of the executable to account for the different ordering. With argument positions you can also re-use the same argument without passing it into the function twice:

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

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

回答by Thilo

Which one is more readable depends on how your head works.

哪一个更具可读性取决于您的大脑如何工作。

You got your answer right there.

你就在那里得到了答案。

It's a matter of personal taste.

这是个人口味的问题。

String concatenation is marginally faster, I suppose, but that should be negligible.

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

回答by Fortega

String.format()is more than just concatenating strings. For example, you can display numbers in a specific locale using String.format().

String.format()不仅仅是连接字符串。例如,您可以使用String.format().

However, if you don't care about localisation, there is no functional difference. Maybe the one is faster than the other, but in most cases it will be negligible..

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

回答by AngerClown

I haven't done any specific benchmarks, but I would think that concatenation may be faster. String.format() creates a new Formatter which, in turn, creates a new StringBuilder (with a size of only 16 chars). That's a fair amount of overhead especially if you are formatting a longer string and StringBuilder keeps having to resize.

我没有做过任何具体的基准测试,但我认为串联可能会更快。String.format() 创建了一个新的 Formatter,它反过来又创建了一个新的 StringBuilder(大小只有 16 个字符)。这是相当大的开销,特别是如果您正在格式化更长的字符串并且 StringBuilder 必须不断调整大小。

However, concatenation is less useful and harder to read. As always, it's worth doing a benchmark on your code to see which is better. The differences may be negligible in server app after your resource bundles, locales, etc are loaded in memory and the code is JITted.

然而,连接的用处不大,而且更难阅读。与往常一样,值得对您的代码进行基准测试以查看哪个更好。在您的资源包、区域设置等加载到内存中并且代码经过 JIT 处理后,服务器应用程序中的差异可能可以忽略不计。

Maybe as a best practice, it would be a good idea to create your own Formatter with a properly sized StringBuilder (Appendable) and Locale and use that if you have a lot of formatting to do.

也许作为最佳实践,使用适当大小的 StringBuilder (Appendable) 和 Locale 创建您自己的 Formatter 是一个好主意,如果您有很多格式要做,请使用它。

回答by Icaro

About 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");
}

The timing results are as follows:

计时结果如下:

  • Concatenation = 265 millisecond
  • Format = 4141 millisecond
  • 串联 = 265 毫秒
  • 格式 = 4141 毫秒

Therefore, concatenation is much faster than String.format.

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

回答by DotNetUser

You cannot compare String Concatenation and String.Format by the program above.

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

You may try this also be interchanging the position of using your String.Format and Concatenation in your code block like the below

您也可以尝试在代码块中交换使用 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") ;
}

You will be surprised to see that Format works faster here. This is since the intial objects created might not be released and there can be an issue with memory allocation and thereby the performance.

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

回答by Pawel Zieminski

There could be a perceptible difference.

可能会有明显的差异。

String.formatis quite complex and uses a regular expression underneath, so don't make it a habit to use it everywhere, but only where you need it.

String.format非常复杂,并且在下面使用了正则表达式,所以不要养成在任何地方都使用它的习惯,而应该只在需要的地方使用它。

StringBuilderwould be an order of magnitude faster (as someone here already pointed out).

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

回答by TechTrip

Since there is discussion about performance I figured I'd add in a comparison that included StringBuilder. It is in fact faster than the concat and, naturally the String.format option.

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

To make this a sort of apples to apples comparison I instantiate a new StringBuilder in the loop rather than outside (this is actually faster than doing just one instantiation most likely due to the overhead of re-allocating space for the looping append at the end of one builder).

为了使这成为一种苹果与苹果的比较,我在循环中而不是在循环之外实例化了一个新的 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] - Format = 1416 millisecond
  • 2012-01-11 16:30:46,190 INFO [TestMain] - Concatenation = 134 millisecond
  • 2012-01-11 16:30:46,313 INFO [TestMain] - String Builder = 117 millisecond
  • 2012-01-11 16:30:46,058 信息 [TestMain] - 格式 = 1416 毫秒
  • 2012-01-11 16:30:46,190 信息 [TestMain] - 连接 = 134 毫秒
  • 2012-01-11 16:30:46,313 信息 [TestMain]-字符串生成器 = 117 毫秒

回答by Reinstate Monica - M. Schr?der

One problem with .formatis that you lose static type safety. You can have too few arguments for your format, and you can have the wrong types for the format specifiers - both leading to an IllegalFormatExceptionat runtime, so you might end up with logging code that breaks production.

一个问题.format是你失去了静态类型安全。您的格式参数可能太少,格式说明符的类型可能错误 - 两者都会导致IllegalFormatExceptionat runtime,因此您最终可能会记录中断生产的代码。

In contrast, the arguments to +can be tested by the compiler.

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

The security historyof printf(on which the formatfunction is modeled) is long and frightening.

安全历史的printf(其上format函数建模)长和可怕。

回答by Akos Cz

Here's the same test as above with the modification of calling the toString()method on the StringBuilder. The results below show that the StringBuilder approach is just a bit slower than String concatenation using the +operator.

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

file: StringTest.java

文件: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 Commands : (compile and run StringTest 5 times)

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

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

Results :

结果 :

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