Many people use 'substring' method.
I found many people simply use 'substring' method in String class.
I was wondering substring of String class cause overhead. so i decompiled String.class.
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
You can see 'new String()' code at the end of the function.
Every time new instance created when it called.
The HackerRank Problem is below.
https://www.hackerrank.com/challenges/reduced-string
It is better to use 'StringBuffer' then 'String'.
Below is deleteCharAt method of 'StringBuffer'.
public AbstractStringBuilder deleteCharAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
System.arraycopy(value, index+1, value, index, count-index-1);
count--;
return this;
}
StringBuffer doesn't make a new instance and reuse one instance.
'copy and paste' of Array class may have performance problem. so It needs to benchmark.
Below is my 10,000 characters benchmark results.You can see a big difference.
Result:
substring time: 33 ms
StringBuffer deleteCharAt time: 8 ms
Result (with warmup):
substring time: 11 ms
StringBuffer deleteCharAt time: 5 ms
Benchark Code
public void benchmark() {
warmUp();
System.out.println("substring time: " + testSubstring());
System.out.println("StringBuffer deleteCharAt time: " + testDeleteCharAt());
}
private void warmUp() {
for (int i=0; i<5000; i++) {
testSubstring();
testDeleteCharAt();
}
}
private long testSubstring() {
long startTime = System.currentTimeMillis();
String longText = "aaaaaaaa ... 10,000 length String ... ";
System.out.println(longText.length());
while(longText.length() > 3) {
longText = longText.substring(1);
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
private long testDeleteCharAt() {
long startTime = System.currentTimeMillis();
String longText = "aaaaaaaa ... 10,000 length String ... ";
StringBuffer buffer = new StringBuffer();
buffer.append(longText);
while(buffer.length() > 3) {
buffer.deleteCharAt(0);
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
If you do not need 'thread safe' it's better to use StringBuilder.
ReplyDeleteStringBuilder is faster than StringBuffer cause non-thread-safe.