Java – why is “. Concat (string)” much faster than “”?
See the English answer > string concatenation: concat() vs "+" operator11
for(int i = 0; i < 100000000L; i++) { String str2 = str + str; }
To "string" concat(“string”):
for(int i = 0; i < 100000000L; i++) { String str2 = str.concat(str); }
Where STR = = "string"
The output I get is consistent with this, although the average difference is usually closer to 61 nanoseconds:
This indicates that even if you loop and assign to a new string Concat is faster than two - thirds When I use a longer string (STR = = "this is a very long, really very long string"), it's faster than a third This is particularly strange because if Concat is faster and should not be compiled into concat?
My main question is: why Concat faster?
Complete code in case you want to run it and experiment:
public class TimeCompare { public static void main(String[] args) { final long times = 100000000L; String str = "String"; long start1 = System.nanoTime(); for(int i = 0; i < times; i++) { String str2 = str + str; } long end1 = System.nanoTime(); long time1 = end1 - start1; System.out.println((double)(time1) / times); System.out.println(); long start2 = System.nanoTime(); for(int i = 0; i < times; i++) { String str2 = str.concat(str); } long end2 = System.nanoTime(); long time2 = end2 - start2; System.out.println((double)(time2) / times); System.out.println(); System.out.println(".concat is faster than \"+\" by " + ((double)(time1 - time2) / times) + " nanoseconds"); } }
Solution
The following is the source code of concat:
public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value,len + otherLen); str.getChars(buf,len); return new String(buf,true); }
"String" "string" is compiled into a new stringbuilder() append(“string”). append(“string”). The source code of tostring(). 1 append uses its superclass', abstractstringbuilder,
public AbstractStringBuilder append(String str) { if (str == null) str = "null"; int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0,len,value,count); count += len; return this; }
After replacing the method call with the source of the method:
/////////////////concat int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = ((Object)value.getClass() == (Object)Object[].class) ? (T[]) new Object[len + otherLen] : (T[]) Array.newInstance(value.getClass().getComponentType(),len + otherLen); System.arraycopy(value,buf,Math.min(value.length,len + otherLen)); System.arraycopy(str.value,str.value.length); return new String(buf,true); ///////////////append if (str == null) str = "null"; int len = str.length(); if (value.length + len - value.length > 0) { int newCapacity = value.length * 2 + 2; if (newCapacity - value.length + len < 0) newCapacity = value.length + len; if (newCapacity < 0) { if (value.length + len < 0) // overflow throw new OutOfMemoryError(); newCapacity = Integer.MAX_VALUE; } value = ((Object)value.getClass() == (Object)Object[].class) ? (T[]) new Object[newCapacity] : (T[]) Array.newInstance(value.getClass().getComponentType(),newCapacity); System.arraycopy(value,(value.length <= newCapacity) ? value.length : newCapacity; } if (0 < 0) { throw new Stringindexoutofboundsexception(0); } if (len > str.value.length) { throw new Stringindexoutofboundsexception(len); } if (0 > len) { throw new Stringindexoutofboundsexception(len - 0); } System.arraycopy(str.value,value.length,len - 0); count += len; return this;
Delete code that will not be executed with the given string and delete the same code between them:
//////////////concat int len = value.length; len + otherLen System.arraycopy(value,len + otherLen)); System.arraycopy(str.value,str.value.length); this.value = value; /////////////////append if(value.length + len - value.length > 0) int newCapacity = value.length * 2 + 2; if(newCapacity - value.length + len < 0) if(newCapacity < 0) System.arraycopy(value,(value.length <= newCapacity) ? value.length : newCapacity); if(0 < 0) if(len > str.value.length) if(0 > len) System.arraycopy(str.value,len - 0); count += len;
After calculating all operations and deleting the same operations between concat and append:
concat -------- int assignment: 0 int +/-: 0 int comparison: 0 char[] assignment: 1 arraycopy: 0 int *: 0 append -------- int assignment: 1 int +/-: 5 int comparison: 6 char[] assignment: 0 arraycopy: 0 int *: 1
You can see that in almost all cases, a concat will be faster than an append and compiled into two appendages and a toString
[1]:A: String concatenation: concat() vs + operator