Course outline · 0% complete

0/29 lessons0%

Course overview →

StringBuilder and string drills

lesson 10-1 · ~11 min · 27/29

From lesson 2-2, word.toUpperCase() runs and word prints unchanged afterwards because Strings are immutable. Methods return a new String rather than changing the original.

A Java String can never change after creation, so every transforming method builds and returns a fresh one.

That immutability is also why building a big string with + in a loop is slow, and the fix is this lesson's StringBuilder.

StringBuilder

Because Strings are immutable, result += piece cannot extend a string. It builds a whole new one, copying everything accumulated so far.

Do that in a loop and n appends cost 1 + 2 + ... + n copies, which is the O(n²) pattern from lesson 10-0 hiding inside one innocent line. Interviewers watch for exactly this.

StringBuilder is a mutable text buffer that appends without recopying, keeping the whole build O(n):

StringBuilder sb = new StringBuilder();
sb.append("Ja");      // O(1) amortized, per lesson 10-0
sb.append("va");
sb.length();          // 4
sb.reverse();         // in place
sb.toString();        // back to a String

Also useful are sb.insert(0, "x"), sb.deleteCharAt(i), sb.charAt(i), and constructing it pre-loaded with new StringBuilder("seed").

Note that reverse() changes the buffer itself rather than returning a new one, which is the whole difference from String. The classic one-liner interview move is reversing a string with new StringBuilder(s).reverse().toString().

result += piece a a b a b c a b c d a new String each step 1 + 2 + 3 + ... copies, so O(n²) sb.append(piece) a b c d appended in place one buffer, no recopying n appends stay O(n)
Repeated string concatenation copies everything built so far on every step, while a StringBuilder appends into one buffer.

Appending, inserting, reversing, and joining

One buffer edited in place, then a second buffer built inside a loop.

public class Main {
  public static void main(String[] args) {
    StringBuilder sb = new StringBuilder("Java");
    sb.append(" rocks");
    sb.insert(0, ">> ");
    System.out.println(sb);
    sb.reverse();
    System.out.println(sb);

    StringBuilder joined = new StringBuilder();
    int[] nums = {1, 2, 3, 4};
    for (int n : nums) {
      if (joined.length() > 0) {
        joined.append(",");
      }
      joined.append(n);
    }
    System.out.println(joined);
  }
}

Output

>> Java rocks
skcor avaJ >>
1,2,3,4

println(sb) prints the buffer contents because StringBuilder has a toString, so no explicit conversion is needed for output.

The joining loop shows the separator idiom: append the comma only when something is already there, which avoids both a leading and a trailing comma. Building the same line with += would be the quadratic version of identical output.

The palindrome pattern

A palindrome reads the same forwards and backwards. The shortest correct check builds the reversed copy and compares:

String s = "racecar";
String reversed = new StringBuilder(s).reverse().toString();
boolean isPalindrome = s.equals(reversed);

The comparison uses equals rather than ==, for the reason from lesson 2-2: these are two separate objects, so == would compare heap locations.

This version costs O(n) time and O(n) extra space for the copy. The two-pointer version in lesson 10-2 does the same job in O(n) time with no copy at all, which is the better answer when an interviewer asks about space.

Real checks usually normalize first, lowercasing and dropping non-letters, since "A man, a plan, a canal: Panama" is a palindrome to a human and not to a naive comparison.

Reversing and testing a word

The reverse idiom used once for output and once for a comparison.

public class Main {
  public static void main(String[] args) {
    String word = "interview";
    System.out.println(new StringBuilder(word).reverse().toString());

    String candidate = "racecar";
    String reversed = new StringBuilder(candidate).reverse().toString();
    System.out.println(candidate + " is a palindrome: " + candidate.equals(reversed));
  }
}

Output

weivretni
racecar is a palindrome: true

word itself is never modified, since the constructor copied its characters into a new buffer and only the buffer was reversed.

equals returns a boolean, and joining a boolean onto a String with + prints true or false, which is why the second line needs no if at all.