Thursday, January 20, 2022

Java Tutorial: StringBuilder

Chapters

StringBuilder and StringBuffer

StringBuilder is like the mutable version of String. StringBuilder is not synchronized and therefore it's not thread safe. However, StringBuilder has a synchronized version which is called StringBuffer. If you need a mutable String that is accessed by multiple threads, consider using StringBuffer. If a mutable String is not accessed by multiple threads, it's recommended to use StringBuilder as the mutable String.

By using StringBuilder or StringBuffer, we can efficiently save memory resources regarding Strings. As you may have known now, String objects are immutable. Everytime we create or "modify" a String, a new String object may be created. I explained how Strings do this in this article.

StringBuilder or StringBuffer doesn't create new object everytime we modify the String value in it. Thus, these two classes are useful if we are modifying a String value lots of times. Once we're done modifying the String value in StringBuilder, we can use the toString() method to create a String object of the String value in the StringBuilder.

StringBuilder or StringBuffer stores elements in a dynamic container similar to ArrayList. By default, this container has a capacity of 16 characters. This capacity will be doubled once the number of characters in the StringBuilder exceeds the maximum capacity of the StringBuilder.

In this tutorial, I'm going to demonstrate some methods in StringBuilder that I think are essential for understanding this class. More infornation and methods can be found in the documentation. The example that I'm gonna demonstrate here is applicable(with few modifications) to StringBuffer since StringBuilder and StringBuffer have identical methods. Also, some methods of StringBuilder are identical to some methods in String class.

append() Method

This method appends a String representation of this method's parameter. This method has multiple forms. Check the documentation to see all method forms.

This example demonstrates append(char c).
public class SampleClass{

  public static void main(String[] args){
  
    StringBuilder builder = 
    new StringBuilder("A");
    
    builder.append('B');
    builder.append('C');
    builder.append('D');
    
    System.out.println(builder.toString());
  }
}

Result
ABCD
capacity() and length() Methods

capactiy() returns the current capacity. The capacity is the number of characters that can be stored (including already written characters), beyond which an allocation will occur.
length() returns the length (character count).

This example demonstrates capacity() and length().
public class SampleClass{

  public static void main(String[] args){
  
    StringBuilder sb = 
    new StringBuilder();
    
    sb.append('A');
    sb.append('B');
    sb.append('C');
    sb.append('D');
    
    System.out.println("Capacity: " + sb.capacity());
    System.out.println("length: " + sb.length());
    System.out.println("Value: " + sb.toString());
  }
}

Result
Capacity: 16
length: 4
Value: ABCD
ensureCapacity() Method

Ensures that the capacity is at least equal to the specified minimum. If the current capacity is less than the argument, then a new internal array is allocated with greater capacity.

This example demonstrates ensureCapacity().
public class SampleClass{

  public static void main(String[] args){
  
    StringBuilder sb1 = 
    new StringBuilder();
    
    System.out.println("sb1 Capacity: " + sb1.capacity());
    System.out.println("ensure capacity...");
    sb1.ensureCapacity(18);
    System.out.println("sb1 Capacity: " + sb1.capacity());
    
    StringBuilder sb2 = 
    new StringBuilder();
    
    System.out.println();
    System.out.println("sb2 Capacity: " + sb2.capacity());
    System.out.println("ensure capacity...");
    sb2.ensureCapacity(35);
    System.out.println("sb2 Capacity: " + sb2.capacity());
    
  }
}

Result
sb1 Capacity: 16
ensure capacity...
sb1 Capacity: 34

sb2 Capacity: 16
ensure capacity...
sb2 Capacity: 35
In the example above, the current capacity is doubled plus 2 additional space. Making the new capacity larger than the capacity that we put in the argument of ensureCapacity(). If the capacity in the argument is greater than the doubled capacity + 2, the current capacity of the StringBuilder is going to be the replaced by the capacity in the argument.

compareTo() Method

Compares two StringBuilder instances lexicographically. This method follows the same rules for lexicographical comparison as defined in the CharSequence.compare(this, another) method.

This example demonstrates ensureCapacity().
public class SampleClass{

  public static void main(String[] args){
  
    StringBuilder sb1 = 
    new StringBuilder();
    
    StringBuilder sb2 = 
    new StringBuilder();
    
    StringBuilder sb3 = 
    new StringBuilder();
    
    sb1.append('A');
    sb1.append('B');
    
    sb2.append('A');
    sb2.append('B');
    
    sb3.append('B');
    sb3.append('C');
    
    System.out.println(sb1.compareTo(sb2));
    System.out.println(sb1.compareTo(sb3));
    
  }
}

Result
0
-1
If the return value of compareTo() is 0, it means that the characters in both StringBuilder objects are equal.

delete() Method

Method Form: public StringBuilder delete(int start, int end)
Removes the characters in a substring of this sequence. The substring begins at the specified start and extends to the character at index end - 1 or to the end of the sequence if no such character exists. If start is equal to end, no changes are made.

This example demonstrates delete().
public class SampleClass{

  public static void main(String[] args){
  
    StringBuilder sb = 
    new StringBuilder();
    
    sb.append(10);
    sb.append(200);
    sb.append("String");
    
    System.out.println("Value: " + sb.toString());
    System.out.println("delete...");
    sb.delete(2,5);
    System.out.println("Value: " + sb.toString());
    
  }
}

Value: 10200String
delete...
Value: 10String
reverse() Method

Method Form: public StringBuilder reverse()
Causes this character sequence to be replaced by the reverse of the sequence. If there are any surrogate pairs included in the sequence, these are treated as single characters for the reverse operation. Thus, the order of the high-low surrogates is never reversed.

Let n be the character length of this character sequence (not the length in char values) just prior to execution of the reverse method. Then the character at index k in the new character sequence is equal to the character at index n-k-1 in the old character sequence.

Note that the reverse operation may result in producing surrogate pairs that were unpaired low-surrogates and high-surrogates before the operation. For example, reversing "\uDC00\uD800" produces "\uD800\uDC00" which is a valid surrogate pair.

Surrogate pair is a pair of two unicode code points that is implemented to UTF-16. You may read more about UTF-16 and surrogate pair in this article.

This example demonstrates reverse().
public class SampleClass{

  public static void main(String[] args){
  
    StringBuilder sb = 
    new StringBuilder();
    
    sb.append('A');
    sb.append('B');
    sb.append('C');
    sb.append('D');
    
    System.out.println("Value: " + sb.toString());
    System.out.println("reverse...");
    sb.reverse();
    System.out.println("Value: " + sb.toString());
  }
}

Value: ABCD
reverse...
Value: DCBA
insert() Method

The characters of the String argument are inserted, in order, into this sequence at the indicated offset, moving up any characters originally above that position and increasing the length of this sequence by the length of the argument. If str is null, then the four characters "null" are inserted into this sequence. This method has multiple forms. More information can be found in the documentation.

This example demonstrates insert().
public class SampleClass{

  public static void main(String[] args){
  
    StringBuilder sb = 
    new StringBuilder();
    
    sb.append('A');
    sb.append('B');
    sb.append('G');
    sb.append('H');
    
    System.out.println("Value: " + sb.toString());
    System.out.println("insert...");
    sb.insert(2,"CDEF");
    System.out.println("Value: " + sb.toString());
  }
}

Result
Value: ABGH
reverse...
Value: ABCDEFGH
setLength() Method

Method Form: public void setLength(int newLength)
Sets the length of the character sequence. The sequence is changed to a new character sequence whose length is specified by the argument. For every nonnegative index k less than newLength, the character at index k in the new character sequence is the same as the character at index k in the old sequence if k is less than the length of the old character sequence.

Otherwise, it is the null character '\u0000'. In other words, if the newLength argument is less than the current length, the length is changed to the specified length.

This example demonstrates setLength().
public class SampleClass{

  public static void main(String[] args){
  
    StringBuilder sb = 
    new StringBuilder();
    
    sb.append('A');
    sb.append('B');
    sb.append('C');
    sb.append('D');
    
    System.out.println("sb length: " + sb.length());
    System.out.println("sb capacity: " + sb.capacity());
    System.out.println("sb value: " + sb.toString());
    System.out.println("setLength...");
    sb.setLength(0);
    System.out.println("sb length: " + sb.length());
    System.out.println("sb capacity: " + sb.capacity());
    System.out.println("sb value: " + sb.toString());
    
    StringBuilder sb2 = 
    new StringBuilder();
    
    sb2.append('A');
    sb2.append('B');
    sb2.append('C');
    sb2.append('D');
    
    System.out.println();
    System.out.println("sb2 length: " + sb2.length());
    System.out.println("sb2 capacity: " + sb2.capacity());
    System.out.println("sb2 value: " + sb2.toString());
    System.out.println("setLength...");
    sb2.setLength(6);
    System.out.println("sb2 length: " + sb2.length());
    System.out.println("sb2 capacity: " + sb2.capacity());
    System.out.println("sb2 value: " + sb2.toString());
    
  }
}

Result
sb length: 4
sb capacity: 16
sb value: ABCD
setLength...
sb length: 0
sb capacity: 16
sb value: 

sb2 length: 4
sb2 capacity: 16
sb2 value: ABCD
setLength...
sb2 length: 0
sb2 capacity: 16
sb2 value: ABCD
In the result above, sb2 value has 4 characters but the total length of sb2 is 6. Those two invisible characters are null characters or '\u0000'. Typically, setLength() is used to clear characters in a StringBuilder.

trimToSize() Method

Method Form: public void trimToSize()
Attempts to reduce storage used for the character sequence. If the buffer is larger than necessary to hold its current sequence of characters, then it may be resized to become more space efficient. Calling this method may, but is not required to, affect the value returned by a subsequent call to the capacity() method.

This example demonstrates trimToSize().
public class SampleClass{

  public static void main(String[] args){
  
    StringBuilder sb = 
    new StringBuilder();
    
    sb.append('A');
    sb.append('B');
    sb.append('C');
    sb.append('D');
    
    System.out.println("sb length: " + sb.length());
    System.out.println("sb capacity: " + sb.capacity());
    System.out.println("sb value: " + sb.toString());
    System.out.println("setLength...");
    sb.setLength(2);
    System.out.println("sb length: " + sb.length());
    System.out.println("sb capacity: " + sb.capacity());
    System.out.println("sb value: " + sb.toString());
    System.out.println("trimToSize...");
    sb.trimToSize();
    System.out.println("sb length: " + sb.length());
    System.out.println("sb capacity: " + sb.capacity());
    System.out.println("sb value: " + sb.toString());
    
  }
}

Result
sb length: 4
sb capacity: 16
sb value: ABCD
setLength...
sb length: 2
sb capacity: 16
sb value: AB
trimToSize...
sb length: 2
sb capacity: 2
sb value: AB

No comments:

Post a Comment