【问题标题】:The most efficient way o 3 Strings concatenation in java 8 [closed]java 8中最有效的3个字符串连接方式[关闭]
【发布时间】:2021-11-24 16:58:10
【问题描述】:

我有一个 Java 8 中的多线程 Http 服务器 它每秒收到数千个请求,并且必须创建需要字符串连接的响应。这个问题的最佳(最快)解决方案是什么?

我知道通常StringBuilder+ 运算符具有更好的性能,我认为 StringBuilder 将是最好的解决方案,但在这种情况下,我必须为每个请求初始化新的 StringBuilder。

此外,在我的问题中,连接总是需要 3 个字符串 - 其中两个是最终的,中间的一个是变量。该变量可以从 ~20 个不同元素的集合中获取值。所以可能的连接字符串的数量等于 20 x number_of_different_strings,大约是 2000

是使用 StringBuilder 更好还是仅仅连接字符串(数量不会超过 2k 个不同的字符串),或者将所有创建的字符串(大约 2k)存储在 map 中并每次询问特定的字符串更好?

【问题讨论】:

  • StringBuilder 并不总是比+ 快​​,你听错或误解了这个建议。问题是,如果您在循环内使用+ 一遍又一遍地连接,那么正确使用StringBuilder 可能会效率更低。但是,如果您所做的只是连接 3 个值而没有任何循环,那么 "foo" + x + "bar" 就可以了。您是否分析过您的代码以验证字符串连接是否真的是这里的问题?
  • StringBuilder 的开销可能会比正常连接更多,除非您为 1 个 request 执行此连接 多次 次。
  • 实际上,每秒 1000 个请求听起来并不可笑。首先进行基准测试。
  • 老实说:你的很多论点都是错误的/具有误导性的,听起来就像那些不真正了解 Java 程序性能以及什么是或不影响他们。您真的真的应该在实际加载场景中配置您的代码,以验证您的代码中花费的时间最多。我的直觉告诉我这不是字符串连接,但直觉在这些领域是非常危险的事情,所以不要相信它们(不是我的也不是你的)。
  • 关于字符串是否有任何已知的限制因素?最大尺寸,总是一样的尺寸,只有 ASCII?

标签: java string performance string-concatenation


【解决方案1】:

我知道一般StringBuilder的性能比+运营商好很多

这并不完全正确。事实上,当您使用+ 运算符时,Java 编译器会将其转换为在编译代码中使用StringBuilder

问题如下。看下面的代码:

String[] names = {"Joe", "Susan", "Fred", "Mary"};

String result = "";
for (String name : names) {
    result = result + name;
}

每次使用+ 运算符时,Java 编译器都会创建一个StringBuilder 来执行该操作。编译器将上面的内容转换成这样的:

for (String name : names) {
    StringBuilder sb = new StringBuilder(result);
    sb.append(name);
    result = sb.toString();
}

请注意,这是非常低效的代码。在循环的每次迭代中,都会创建一个新的StringBuilder 对象。字符串result 中包含的数据被复制到StringBuilder 中。然后将下一个名称附加到它上面,然后将StringBuilder 中的数据复制到分配给result 的新String 中。有很多不必要的复制。

您可以直接使用StringBuilder 编写更高效的代码:

StringBuilder sb = new StringBuilder();
for (String name : names) {
    sb.append(name);
}
String result = sb.toString();

这样,只会创建一个StringBuilder 对象,并且不会在循环的每次迭代中将数据复制到其中,而是复制到String

如果您的代码不涉及在循环中附加许多字符串,而您只需连接三个字符串,那么显式使用+StringBuilder 就没有关系。事实上,使用+ 编写的代码将被编译成与手动使用StringBuilder 时编写的代码完全相同。

【讨论】:

  • 自 Java 9 版本以来,编译器并未将结构完全转换为 StringBuilder chaing,而是 uses invokedynamic to invoke "deep Java magic" ;-) 您的回答的总体信息仍然非常适用。
  • 是的,我的回答可能不是完全 Java 编译器在做什么;这是为了说明为什么在循环中使用带有+的字符串连接效率较低。
猜你喜欢
  • 2010-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-23
  • 2015-12-18
  • 2013-09-24
相关资源
最近更新 更多