Java 是不是+&引用;在字符串连接中使用会影响效率吗?

Java 是不是+&引用;在字符串连接中使用会影响效率吗?,java,string,performance,stringbuffer,Java,String,Performance,Stringbuffer,我在java中使用过String、StringBuilder和StringBuffer。 我是从效率的角度思考这个问题的 在字符串连接中使用“+”是否会影响效率?有点肯定,但仍然否 来自JLS,15.18.1.2 字符串连接优化 实现可以选择执行转换和串联 在一个步骤中避免创建然后丢弃中间 字符串对象。以提高重复字符串的性能 连接时,Java编译器可以使用StringBuffer类或 减少中间字符串对象数量的类似技术 通过表达式求值创建的 对于基元类型,实现还可以通过直接从基元类型转换为字符串来

我在java中使用过String、StringBuilder和StringBuffer。
我是从效率的角度思考这个问题的


在字符串连接中使用“+”是否会影响效率?有点肯定,但仍然

来自JLS,15.18.1.2

字符串连接优化

实现可以选择执行转换和串联 在一个步骤中避免创建然后丢弃中间 字符串对象。以提高重复字符串的性能 连接时,Java编译器可以使用StringBuffer类或 减少中间字符串对象数量的类似技术 通过表达式求值创建的


对于基元类型,实现还可以通过直接从基元类型转换为字符串来优化包装器对象的创建。

是的,但这一点在大多数情况下都无关紧要

对字符串常量使用“+”是最有效的,因为编译器可以执行串联

如果要连接两个字符串,则
concat
方法是最有效的,因为它可以避免使用StringBuilder

除了向后兼容之外,几乎没有任何理由使用StringBuffer。StringBuilder或StringWriter是更好的选择。但是,在JDK:P中,它仍然比StringBuilder更经常地被显式使用


如果在单个语句中进行连接,那么这并不重要,因为编译器/JIT编译器将使用
StringBuilder
自动对其进行优化

因此
“a”+b+“c”
将被优化为
(新的StringBuilder(“a”).append(b).append(“c”).toString()

但是,如果要在循环中连接大量的
String
s,请明确使用
StringBuilder
,因为它将显著加快程序的速度

String a = "";

for( int i = 0; i < 1000000; i++ )
    a += i;
字符串a=”“;
对于(int i=0;i<1000000;i++)
a+=i;
应改为

StringBuilder sb = new StringBuilder();

for( int i = 0; i < 1000000; i++ )
    sb.append(i);

String a = sb.toString();
StringBuilder sb=新建StringBuilder();
对于(int i=0;i<1000000;i++)
某人(i);
字符串a=sb.toString();

由于字符串是不可变的,因此连接字符串会导致创建字符串。即。。“A”+“B”+“C”导致创建“AB”,然后创建“ABC”。如果您正在进行多个连接,那么使用StringBuilder(不是旧的但api相同的StringBuffer,它有同步成本)总是会更有效

如果您有单行连接,编译器将尽可能为您执行此操作-也就是说,如果您编译“a”+“B”+“C”,您可能会看到,如果您反编译,类似于new StringBuilder(“a”).append(“B”).append(“C”).toString()。但是,编译器无法在多行上优化多个字符串concats,也就是说,如果您有多个连接行,您将在每行上看到类似于上面的内容,包括额外的StringBuilder创建。最好是手工操作

您可以通过组合一个简单的示例并进行反编译来验证这一点。

在您的示例中:

" Does +" + " use in String concatenation affect efficiency? "
我们必须使用文本字符串,这可能会被编译器替换,因此这将比StringBuffer/append/toString更快

但与什么相比,效率/速度更快?代码执行?代码编写?代码读取

自从读了一本书

"Foo = " + foo;
这很容易,我推荐它,只要它不重复一百万次,或者“s+=s2;”不重复一百次

特别是

System.out.println ("Player " + n + " scores " + player[n].score); 
它的可读性比

System.out.println (new StringBuffer ("Player ").append ((Integer.valueOf (n)).toString ().append (" scores ").append (...

在需要高性能的应用程序中,或者连接大量字符串,或者以递归方式连接大量字符串时,请避免使用它。

如果要使用多次与“+”连接,则在某种程度上是。因为 当您使用字符串a+字符串b时,它实际上会在内部创建一个StringBuffer对象,并使用StringBuffer的append()。因此,每次执行“+”操作时,都会创建一个新的临时StringBuffer对象,用“a”初始化,然后附加“b”,然后将其转换为字符串对象


因此,如果您需要多个连接,您应该创建一个StringBuffer(线程安全)/StringBuilder(非线程安全)对象并保持附加,这样可以避免一次又一次地创建StringBuffer对象

我想这已经在这里讨论了很多了,所以?是的,我认为规则是,如果要连接两个以上的字符串,应该使用stringbuilder。。。如果你提前有了一个想法/答案,(1)把它作为额外的信息放在问题中,或者(b)不要问你已经知道答案的问题。如果是小串接的话,“那么少”。但是,我曾经处理过一个包含许多串联(解析器/过滤器)的类,其中简单地从串联更改为缓冲区附加可以将执行时间(非常慢)减少一半。微基准也不太可能向您显示添加所有这些额外中间字符串对象的垃圾收集成本,但它们将在应用程序的生命周期内摊销。在我的应用程序中,我使用线程本地ByteBuffer,并使用不创建任何对象的方法直接读取/写入。这对于99%的用例来说是非常极端的,但它可以让您的登录时间缩短到几微秒只有在多个语句中展开字符串时,“multiple”才是正确的。带+的单个语句与单个stringbuilder一样高效,但可读性更好(而且编译器可以更好地优化初始大小)。我很确定第二段提到了这一点。这是错误的,如果您编写“A”+“B”+“C”,则不会得到中间字符串。