Ответ 1
Изменить: Оглядываясь назад на этот ответ, я теперь понимаю, насколько он ненаучный и умозрительный. Хотя это не обязательно неправильно, я больше не уверен в его правильности.
Вот исходный код для 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"
компилируется в new StringBuilder().append("string").append("string").toString()
. 1append
источник использует свой суперкласс ', AbstractStringBuilder
, method:
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;
}
После замены вызова метода с помощью источника метода:
/////////////////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, 0, buf, 0, Math.min(value.length, len + otherLen));
System.arraycopy(str.value, 0, buf, len, 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, 0, value, 0, (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, 0, value, value.length, len - 0);
count += len;
return this;
После удаления кода, который никогда не будет выполняться с данной строкой, и удаления между ними одинакового кода:
//////////////concat
int len = value.length;
len + otherLen
System.arraycopy(value, 0, buf, 0, Math.min(value.length, len + otherLen));
System.arraycopy(str.value, 0, buf, len, 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, 0, value, 0, (value.length <= newCapacity) ? value.length : newCapacity);
if(0 < 0)
if(len > str.value.length)
if(0 > len)
System.arraycopy(str.value, 0, value, value.length, len - 0);
count += len;
После подсчета всех операций и операций удаления, которые совпадают между concat и 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
Вы можете видеть, что один concat будет быстрее, чем один append почти во всех случаях, а +
скомпилируется в два приложения и toString
.