Skip to main content

substring method performance in Java 1.8 String Class


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;
}




Comments

  1. If you do not need 'thread safe' it's better to use StringBuilder.
    StringBuilder is faster than StringBuffer cause non-thread-safe.

    ReplyDelete

Post a Comment