Concat整数到字符串 - 从性能和内存的角度来看,使用字符串文字或原语?

时间:2013-02-08 23:07:51

标签: java string concatenation primitive

选项1:

String newStr = someStr + 3 + "]";

选项2:

String newStr = someStr + "3" + "]";

哪种选择在性能,记忆和一般练习方面更好? 我可以使用哪些推荐的工具/方法来测量代码的内存使用情况及其性能(除了测量开始时间和结束时间以及计算差异)

5 个答案:

答案 0 :(得分:10)

第一个将成为:

StringBuilder sb = new StringBuilder (String.valueOf (someStr));
sb.append (3);
sb.append ("]");
String newStr = sb.toString ();

第二个将成为:

StringBuilder sb = new StringBuilder (String.valueOf (someStr));
sb.append ("3");
sb.append ("]");
String newStr = sb.toString ();

这是反汇编:

public String foo (String someStr)
{
    String newStr = someStr + 3 + "]";
    return newStr;
}

public String bar (String someStr)
{
    String newStr = someStr + "3" + "]";
    return newStr;
}

public java.lang.String foo(java.lang.String);
Code:
   0: new           #16                 // class java/lang/StringBuilder
   3: dup
   4: aload_1
   5: invokestatic  #18                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   8: invokespecial #24                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  11: iconst_3
  12: invokevirtual #27                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
  15: ldc           #31                 // String ]
  17: invokevirtual #33                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  20: invokevirtual #36                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  23: astore_2
  24: aload_2
  25: areturn

public java.lang.String bar(java.lang.String);
Code:
   0: new           #16                 // class java/lang/StringBuilder
   3: dup
   4: aload_1
   5: invokestatic  #18                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   8: invokespecial #24                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  11: ldc           #44                 // String 3
  13: invokevirtual #33                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  16: ldc           #31                 // String ]
  18: invokevirtual #33                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  21: invokevirtual #36                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  24: astore_2
  25: aload_2
  26: areturn

答案 1 :(得分:7)

两者之间不会有任何明显的差异。使用您认为最具逻辑性和可读性的内容。我会用

String newStr = someStr + "3]";

答案 2 :(得分:3)

我建议Jprofiler作为一个很棒的java应用程序分析工具,帮助我找到很多内存问题。

我不认为选项1和2在内存使用方面有很大差异,特别是如果它适用于桌面应用程序。

答案 3 :(得分:2)

假设someString是常量,两者都是常量表达式,并将在编译时进行评估。它们将导致相同的类文件和运行时行为。

来源:Java Language Specification写道:

  

编译时常量表达式是表示基本类型值的表达式或不突然完成的字符串,仅使用以下内容组成:

     
      
  • String类型的原始类型和文字的文字(§3.10.1,§3.10.2,§3.10.3,§3.10.4,§3.10.5)

  •   
  • 加法运算符+-(第15.18节)

  •   
  • ...

  •   
     

String类型的编译时常量表达式总是“实例化”,以便使用String.intern方法共享唯一实例。

如果someString不是常量,大多数现代编译器将使用StringBuilder,它由Java语言规范明确permitted

  

字符串连接的结果是对String对象的引用,该对象是两个操作数字符串的串联。左侧操作数的字符位于新创建的字符串中右侧操作数的字符之前。

     

除非表达式是编译时常量表达式(第15.28节),否则新创建String对象(第12.5节)。

     

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

     

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

答案 4 :(得分:0)

每当您连接一个字符串时,在每个连接上,您都会创建一个字符串的新副本,并且两个字符串都会被复制,一次只能复制一个字符。这导致时间复杂度为O(n 2 )(McDowell)。

如果您想提高效果,请使用

StringBuilder

其构造函数之一具有以下语法:

public StringBuilder(int size); //Contains no character. Initial capacity of 'size'. 

StringBuilder(可变字符序列。记住字符串是不可改变的)通过简单地创建所有字符串的可调整大小的数组来帮助解决这个问题。只在必要时将它们复制回字符串(McDowell)。

StringBuilder str = new StringBuilder(0);
str.append(someStr);
str.append(3);
str.append("]");

参考:

McDowell,Gayle Laakmann。 Cracking The Coding Interview,第6版。打印。

&#34; Stringbuilder(Java Platform SE 8)&#34;。 Docs.oracle.com。 N.p.,2016。网站。 2016年6月4日。