简体   繁体   English

字符串连接成StringBuilder java

[英]String concatenation into StringBuilder java

I have a legacy Java file which uses String concatenation to build huge String objects.Its a serious performance issue.Is there a method as such which does the following 我有一个遗留Java文件,它使用字符串连接来构建巨大的String对象。这是一个严重的性能问题。是否存在这样的方法,它执行以下操作

String test="I am a very bad programmer"
+"to use concatenation"
+"Instead of StringBuilder"
+" or StringBuffer";

to

StringBuilder strBuilder= new StringBuilder();
strBuilder.append("I am a bad programmer");
strBuilder.append("to use concatenation");
strBuilder.append("Instead of StringBuilder");
strBuilder.append(" or StringBuffer");
String str= strBuilder.toString();

basically I need a stub in java just to give a the String instantiation as input and convert into StringBuilder.Anybody tried this in the past? 基本上我需要一个java中的存根只是为了给一个String实例化作为输入并转换成StringBuilder.Anybody过去试过这个?

No, it isn't a performance issue. 不,这不是性能问题。 If you are concatenating the string inline (just like you showed) rather than using a loop for example, then the compiler automatically transforms the + to using a StringBuilder . 如果你串联内联字符串(就像你展示的那样)而不是使用循环,那么编译器会自动将+转换为使用StringBuilder Check the documentation of java.lang.String 查看java.lang.String的文档

The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. Java语言为字符串连接运算符(+)提供特殊支持,并为其他对象转换为字符串。 String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method. 字符串连接是通过StringBuilder(或StringBuffer)类及其append方法实现的。 String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java. 字符串转换是通过方法toString实现的,由Object定义并由Java中的所有类继承。 For additional information on string concatenation and conversion, see Gosling, Joy, and Steele, The Java Language Specification. 有关字符串连接和转换的其他信息,请参阅Gosling,Joy和Steele,Java语言规范。

Even further - the compiler may use the fact that these are all string constants and join them even before runtime ( JLS references ) 更进一步 - 编译器可能会使用这些都是字符串常量并在运行时( JLS 引用 )之前连接它们的事实

A fixed literal like in your example is more efficient than using a StringBuilder. 像示例中的固定文字比使用StringBuilder更有效。

The fixed literal will be detected by the compiler and will be inlined as a single value, so the two lines 固定文字将由编译器检测,并将内联为单个值,因此两行

String s = "one" + "two" + "three";

and

String s = "onetwothree";

will generate exactly the same bytecode. 将生成完全相同的字节码。

The picture is different though if the concatenation is not done with literals but with function calls. 如果连接不是使用文字而是使用函数调用,则图片是不同的。

When you need to append strings dynamically, prefer StringBuilder over StringBuffer because it is slightly faster as it is not synchronized. 当你需要动态追加字符串时,首选StringBuilder而不是StringBuffer,因为它不会同步,因为它稍快一些。

Here is the example bytecode: 这是示例字节码:

public class Test
{
   private String s = "one" + "two" + "three";
}

public class Test2
{
   private String s2 = "onetwothree";
}

the generated bytecode for these classes is: 这些类的生成字节码是:

c:\Temp>javap -c Test
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   aload_0
   5:   ldc     #2; //String onetwothree
   7:   putfield        #3; //Field s:Ljava/lang/String;
   10:  return
}
c:\Temp>javap -c Test2
Compiled from "Test2.java"
public class Test2 extends java.lang.Object{
public Test2();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   aload_0
   5:   ldc     #2; //String onetwothree
   7:   putfield        #3; //Field s:Ljava/lang/String;
   10:  return
}

As you can see both variables are treated the same way. 正如您所看到的,两个变量的处理方式相同。

I don't think this belongs to the language specification, as this is "just" a compiler optimization. 我不认为这属于语言规范,因为这只是“编译器优化”。

A different compiler (I was using the Sun compiler) might be doing something completely different - which is OK as long as the behaviour doesn't change. 一个不同的编译器(我使用的是Sun编译器)可能会做一些完全不同的事情 - 只要行为没有改变就可以了。

Actually the compiler already applies that optimization for you in the latest versions of Java (at least from 1.5, I think). 实际上,编译器已经在最新版本的Java中为您应用了该优化(至少从1.5开始,我认为)。

What happens when Java Compiler sees many String concatenations in one line? 当Java Compiler在一行中看到许多String连接时会发生什么?

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.18.1.2 http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.18.1.2

Just constant string contatenation is optimised at compile time, and is trivial. 只是常量字符串连接在编译时被优化,并且是微不足道的。 The issue is when you do something less trivial: 问题是当你做一些不那么微不足道的事情时:

String example1 = "Prefix" + variableString1 + "Suffix"; String example1 =“Prefix”+ variableString1 +“Suffix”;

the worst case is loops with appending where every iteration needs to create a new string. 最糟糕的情况是循环,附加每个迭代需要创建一个新字符串。 Since this is common for buffered reads of files you can get very big strings being recreated, a problem I had recently. 因为这对缓冲的文件读取很常见,所以你可以重新创建非常大的字符串,这是我最近遇到的一个问题。

While I see why you'd want to do what you do, the structures of the code are too different to just drop in and replace, and a script to edit the code would have to be quite advanced to be able to deal with all the references. 虽然我明白为什么你想要做你做的事情,代码的结构太不同了,只是插入和替换,编辑代码的脚本必须非常先进,以便能够处理所有的引用。 Maybe there is a way with annonomous inner classes though that can let you keep the same string reference but wrap the actual construction in string builders. 也许有一种方法可以使用自治内部类,但是可以让你保持相同的字符串引用,但是在字符串构建器中包含实际的构造。 It's probably no different than what the optimiser already does though 它可能与优化器已经做的没什么不同

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM