Sun*_*hoo 27 java string-concatenation
对于字符串连接,我们可以使用concat()或concat运算符(+).
我尝试了以下性能测试,发现concat()字符串连接速度更快,内存效率更高.
字符串连接比较100,000次:
String str = null;
//------------Using Concatenation operator-------------
long time1 = System.currentTimeMillis();
long freeMemory1 = Runtime.getRuntime().freeMemory();
for(int i=0; i<100000; i++){
str = "Hi";
str = str+" Bye";
}
long time2 = System.currentTimeMillis();
long freeMemory2 = Runtime.getRuntime().freeMemory();
long timetaken1 = time2-time1;
long memoryTaken1 = freeMemory1 - freeMemory2;
System.out.println("Concat operator :" + "Time taken =" + timetaken1 +
" Memory Consumed =" + memoryTaken1);
//------------Using Concat method-------------
long time3 = System.currentTimeMillis();
long freeMemory3 = Runtime.getRuntime().freeMemory();
for(int j=0; j<100000; j++){
str = "Hi";
str = str.concat(" Bye");
}
long time4 = System.currentTimeMillis();
long freeMemory4 = Runtime.getRuntime().freeMemory();
long timetaken2 = time4-time3;
long memoryTaken2 = freeMemory3 - freeMemory4;
System.out.println("Concat method :" + "Time taken =" + timetaken2 +
" Memory Consumed =" + memoryTaken2);
Run Code Online (Sandbox Code Playgroud)
结果
Concat operator: Time taken = 31; Memory Consumed = 2259096
Concat method : Time taken = 16; Memory Consumed = 299592
Run Code Online (Sandbox Code Playgroud)
如果concat()比运算符更快,那么我们何时应该使用连接运算符(+)?
Art*_*tem 37
concat方法总是生成一个带有连接结果的新String.
plus运算符由StringBuilder创建支持,附加所需的所有String值,并进一步调用toString().
所以,如果你需要连接两个值,concat()将是更好的选择.如果需要连接100个值,则应使用加号运算符或显式使用StringBuilder(例如,如果在循环中追加).
Evg*_*eev 12
实际上s1 + s2和s1.concat(s2)是非常不同的.
s1 + s2由javac转换为
(new StringBuilder(String.valueOf(s1)).append(s2).toString();
Run Code Online (Sandbox Code Playgroud)
如果你反编译.class你可以看到它.这种结构效率不高; 它涉及最多三个新的char []分配和三个char []复制操作.
s1.concat(s2)总是一个新的char [] +一个复制操作,参见String.java
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
char buf[] = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);
return new String(0, count + otherLen, buf);
}
Run Code Online (Sandbox Code Playgroud)
请注意,新的String(int,int,char [])是String的包私有构造函数.它直接使用char buf [],没有通常的复制,以确保字符串不变性的buf不可见性.
您的测试需要运行至少2秒,每个循环在一个单独的方法中才有意义.短期测试可能难以重现和比较.从您的时间看,您似乎正在使用Windows(即因为您的时间是16和31毫秒;)请尝试使用System.nanoTime().当你的循环迭代超过10,000次时,整个方法被编译.这意味着您的后一个方法在启动时已经编译.
在回答你的问题时,在添加两个字符串时,concat会略微加快.但是,它带有打字和概念开销,可能比您节省的CPU大得多.即使你的测试重复100,000次,它也可以节省不到15毫秒的时间,而且它的成本远远超过你的时间(这可能更有价值)你可以在未来版本的JVM中找到它,总是优化差异,代码的复杂性仍然存在.
编辑:我没有注意到内存结果是可疑的.
String str = null;
//------------Using Concatenation operator-------------
long time1 = System.currentTimeMillis();
long freeMemory1 = Runtime.getRuntime().freeMemory();
for (int i = 0; i < 10000; i++) {
str = "Hi";
str = str + " Bye";
}
long time2 = System.currentTimeMillis();
long freeMemory2 = Runtime.getRuntime().freeMemory();
long timetaken1 = time2 - time1;
long memoryTaken1 = freeMemory1 - freeMemory2;
System.out.println("Concat operator :" + "Time taken =" + timetaken1 + " Memory Consumed= " + memoryTaken1);
str = null;
//------------Using Concat method-------------
long time3 = System.currentTimeMillis();
long freeMemory3 = Runtime.getRuntime().freeMemory();
for (int j = 0; j < 10000; j++) {
str = "Hi";
str = str.concat(" Bye");
}
long time4 = System.currentTimeMillis();
long freeMemory4 = Runtime.getRuntime().freeMemory();
long timetaken2 = time4 - time3;
long memoryTaken2 = freeMemory3 - freeMemory4;
System.out.println("Concat method :" + "Time taken =" + timetaken2 + " Memory Consumed= " + memoryTaken2);
Run Code Online (Sandbox Code Playgroud)
运行时打印 -XX:-UseTLAB -mx1g
Concat operator :Time taken =12 Memory Consumed= 1291456
Concat method :Time taken =7 Memory Consumed= 560000
Run Code Online (Sandbox Code Playgroud)
使内存使用率约为2:1.在原始问题中,每次运行时结果都会有所不同,有时.concat()似乎会使用更多.