繁体   English   中英

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

[英]Concat an integer to a String - use String literal or primitive from performance and memory point of view?

选项1:

String newStr = someStr + 3 + "]";

选项2:

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

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

第一个将成为:

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

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

String newStr = someStr + "3]";

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

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

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

来源: Java语言规范写道:

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

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

  • 加法运算符+- (§15.18)

  • ...

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

如果someString不是常量,大多数现代编译器将使用StringBuilder,这是Java语言规范明确允许的:

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

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

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

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

每当您连接一个字符串时,在每个连接上,您都会创建一个新的字符串副本,并且两个字符串都会被复制,一次只能复制一个字符。 这导致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版。 打印。

“Stringbuilder(Java Platform SE 8)”。 Docs.oracle.com。 Np,2016。网站。 2016年6月4日。

暂无
暂无

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

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