Comparing String and StringBuilder Manipulations in Memory Usage

According to the KathySierra SCJP Tutorial:

The java.lang.StringBuffer and java.lang.StringBuilder classes should when you need to make changes to character strings. As we discussed, String objects are immutable, so if you decide to do this a lot of manipulation of String objects, you will get many abandoned String objects in the string pool

To fix this, I looked at the String class code and the StringBuilder source here .

A simple line code is as follows:

public final class String(){
     private final char [] value; //Final helps in immutability, I guess.
     public String (String original){
         value = original.value;
      }
}

And the StringBuildersimplified version is as follows:

public final class StringBuilder{
    char [] value;
    public StringBuilder(String str) {
        value = new Char[(str.length() + 16)]; // 16 here is implementation dependent.
    append(str);
}

public StringBuilder append(String str){

            //Add 'str' characters in value array if its size allows,
        else
            // Create new array of size newCapacity and copy contents of 'value' in that.
            //value = Arrays.copyOf(value, newCapacity);// here old array object is lost.

        return this;
    }
}

So, let's say we have a case like:

Using the String class:

String s1 = "abc"; // Creates one object on String pool.
s1 = s1+"def"; // Creates two objects - "def " on String pool
// and "abcdef" on the heap.

If I use StringBuilder, the code will look like this:

 StringBuilder s1 = StringBuilder("abc");

 // Creates one String object "abc " on String pool.
 // And one StringBuilder object "abc" on the heap.
 s1.append("def");
 // Creates one string object "def" on String pool.
 // And changes the char [] inside StringBuilder to hold "def" also.

StringBuilder s2 = s1.append("def"); , char, , char. .

:

String StringBuilder append(), String, , .

StringBuilder char, String char , , .

  • StringBuilder , String ?
  • , SCJP Guide, ?
+4
4

expandCapacity:

void expandCapacity(int minimumCapacity) {
    int newCapacity = (value.length + 1) * 2; //important part here
    if (newCapacity < 0) {
        newCapacity = Integer.MAX_VALUE;
    } else if (minimumCapacity > newCapacity) {
        newCapacity = minimumCapacity;
    }
    value = Arrays.copyOf(value, newCapacity);
}

2 , , , 1 , .

Wikipedia :

n , . , n O (n) , , . a : a (a-1), (a-1) n. a : a = 2, Java ArrayList a = 3/2, C Python a = 9/8.

, , 30% . 1/a .

.

, :

public static void main(String[] args){
    int numAppends = 200000;
    int numRepetitions = 3;
    long[] time1 = new long[numRepetitions];
    long[] time2 = new long[numRepetitions];
    long now;
    for (int k = 0; k < numRepetitions; k++){
        String s = "";
        now = System.nanoTime();
        for(int i = 0; i < numAppends ; i++) {
            s = s + "a";
        }
        time1[k] = (System.nanoTime() - now) / 1000000;
        StringBuilder sb = new StringBuilder();
        now = System.nanoTime();
        for(int i = 0; i < numAppends ; i++) {
            sb.append("a");     
        }
        time2[k] = (System.nanoTime() - now) / 1000000;
        System.out.println("Rep "+k+", time1: "+time1[k]+ " ms, time2: " + time2[k] + " ms");
    }
}

:

Rep 0, time1: 13509 ms, time2: 7 ms
Rep 1, time1: 13086 ms, time2: 1 ms
Rep 2, time1: 13167 ms, time2: 1 ms

, , Arrays.copyOf() extendCapacity() : 49 , 15 . :

newCapacity: 34
newCapacity: 70
newCapacity: 142
newCapacity: 286
newCapacity: 574
newCapacity: 1150
newCapacity: 2302
newCapacity: 4606
newCapacity: 9214
newCapacity: 18430
newCapacity: 36862
newCapacity: 73726
newCapacity: 147454
newCapacity: 294910
newCapacity: 42
Rep 2, time1: 12955 ms, time2: 134 ms
+6

, , . , :

String[] strings = { "a", "b", "c", "d" };
String result = "";
for( String s : strings) {
    result += s;
}

StringBuilder GC:

String[] strings = { "a", "b", "c", "d" };
StringBuilder builder = new StringBuilder();
for( String s : strings) {
    builder.append(s);
}

GC , .

, , .

+3

- . , . , ? . StringBuilder insert(int offset, c)

. StringBuilder javadoc

delete(int start, int end)
// Removes the characters in a substring of this sequence.

replace(int start, int end, String str)
// Replaces the characters in a substring of this sequence with characters in the specified String.

reverse()
// Causes this character sequence to be replaced by the reverse of the sequence.

insert(int dstOffset, CharSequence s)
// Inserts the specified CharSequence into this sequence.
+2

StringBuilder , String ?

, . , , , <, >, &, ", ' XML HTML:

public static String xmlEscape(String s) {
    StringBuilder sb = new StringBuilder(
        (int)Math.min(Integer.MAX_VALUE, s.length() * 5L / 4));
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (c == '<') sb.append("&lt;");
        else if (c == '>') sb.append("&gt;");
        else if (c == '&') sb.append("&amp;");
        else if (c == '"') sb.append("&quot;");
        else if (c == '\'') sb.append("&#039;");
        else sb.append(c);
    }
    return sb.toString();
}

StringBuilder , , . , , , .

String StringBuilder, , , (.. !) .

:

, SCJP?

, . , " String". , "String pool" , String.intern(). , Strings , ClassLoader .

String , , - ( .intern()).

SCJP:

String , , , String .

Abandoned objects on the heap are not the biggest problem, because the garbage collector will quickly eat them. The real reason for using StringBuilders when doing a few manipulations is to avoid unnecessarily copying characters in the first place. This significantly affects performance, as shown in the @jmiserez test.

+1
source

All Articles