The Stacks
UNIT 1: USING OBJECTS AND METHODS · TOPIC 1.15

1.15 String Manipulation

The single most-tested class on the exam. Know every method on the reference sheet and the three traps that account for most lost points.

What you need to know

  • Strings are immutable: methods return a new String; the original never changes. s.toUpperCase() by itself does nothing unless you store the result.
  • Indices start at 0. The last character is at length() - 1.
  • length() — number of characters. substring(from, to) — characters from index from up to but not including to. substring(from) — from that index to the end.
  • indexOf(str) — index of the first occurrence, or −1 if absent. charAt is not on the reference sheet; use substring(i, i + 1) to get one character as a String.
  • equals(other) — true if contents match. == compares references and is wrong for comparing String contents.
  • compareTo(other) — returns a negative int if this comes before other alphabetically, 0 if equal, positive if after. It's an int, never a boolean. Uppercase letters come before lowercase.
  • Also available: toUpperCase(), toLowerCase(), and string concatenation with +. Concatenating anything with a String produces a String.
  • A String literal with escape sequences: "\"quoted\"", "line1\nline2".

Worked example

String s = "Computer";
s.length();               // 8
s.substring(3, 6);        // "put"   (indices 3,4,5)
s.substring(5);           // "ter"
s.indexOf("put");         // 3
s.indexOf("z");           // -1
s.substring(0, 1);        // "C"  (one character)
"apple".compareTo("banana");    // negative
"Zebra".compareTo("apple");     // negative: 'Z' < 'a'
s.equals("Computer");     // true
s == "Computer";          // unreliable — never use for content

s.toUpperCase();          // returns "COMPUTER" but s is still "Computer"
s = s.toUpperCase();      // now s is "COMPUTER"
Exam tip: Three checks on every String question: (1) substring's second index is exclusive — count characters from from to to - 1; (2) any content comparison must use .equals, never ==; (3) compareTo gives an int, so if (a.compareTo(b)) won't compile — you need < 0, == 0, or > 0.

Going deeper

The nuance, edge cases, and connections that turn a 3 into a 5.

  • Every String method returns a new String or a value; none modify the original. This is immutability. s.toUpperCase() on its own line does nothing visible. s = s.toUpperCase() reassigns s to the new String.
  • substring(from, to): characters at indices from, from+1, …, to−1. Length of result = to − from. substring(from): from to the end. substring(i, i) is the empty string. substring(i, i + 1) is one character — this is the exam's replacement for charAt.
  • Valid substring indices: 0 ≤ from ≤ to ≤ length(). Note that to can equal length() (that's "to the end"). from > to or to > length() throws StringIndexOutOfBoundsException.
  • indexOf(str) returns the index where str starts, or −1. Only the first occurrence. "banana".indexOf("an") is 1. To find later occurrences, search a substring of the remainder.
  • compareTo compares character by character using Unicode values. Uppercase letters (65–90) come before lowercase (97–122), so "Zoo".compareTo("apple") is negative. If one string is a prefix of the other, the shorter one is smaller. The magnitude of the result is the difference of the first differing characters (or lengths) — but the exam only cares about the sign.
  • equals is case-sensitive: "Hi".equals("hi") is false. To compare ignoring case, lowercase both first.
  • length() counts all characters including spaces and punctuation. "a b".length() is 3.
  • Concatenation makes a new String, so building a long String in a loop by += creates many intermediate Strings. Fine at exam scale; worth knowing why StringBuilder exists in real code.

Mistakes that cost points

  • Including the end index in substring. "hello".substring(1, 3) is "el", not "ell".
  • Using == on Strings. Sometimes true for literals, unreliable in general, and the exam treats it as wrong. Use .equals.
  • Treating compareTo as boolean. if (a.compareTo(b)) won't compile. Compare the int to 0.
  • Forgetting immutability. Calling a String method without storing the result changes nothing.
  • Using charAt. Not on the reference sheet. substring(i, i + 1) instead.

Practice questions

Written in the style of the real exam. Try each one before revealing the answer.

Q1 What is printed by the following code?
String w = "programming";
System.out.println(w.substring(3, 7) + w.indexOf("g"));
  1. A gram3
  2. B gramm3
  3. C gram10
  4. D ram3
Show answer

Answer: A. substring(3, 7) is indices 3–6: "gram". indexOf("g") is the first g, at index 3. Concatenated: "gram3".

Q2 Which expression correctly checks whether the String a comes alphabetically before the String b?
  1. A a < b
  2. B a.compareTo(b) < 0
  3. C a.compareTo(b)
  4. D a.equals(b) < 0
Show answer

Answer: B. compareTo returns a negative int when a precedes b. Strings can't be compared with <, and equals returns a boolean.

Q3 What is printed by the following code?
String s = "hello";
s.toUpperCase();
System.out.println(s);
  1. A HELLO
  2. B hello
  3. C Hello
  4. D A compile-time error
Show answer

Answer: B. Strings are immutable. toUpperCase() returns a new String that was discarded; s is unchanged.

Q4 Which of the following returns the last character of a non-empty String s as a String?
  1. A s.substring(s.length())
  2. B s.substring(s.length() - 1)
  3. C s.substring(s.length() - 1, s.length() - 1)
  4. D s.charAt(s.length() - 1)
Show answer

Answer: B. substring(length - 1) returns from the last index to the end — one character. Option A returns an empty string; C returns empty (from == to); D returns a char, and charAt isn't on the reference sheet.

Key vocabulary

Immutable
cannot be changed; String methods return new Strings
substring(a, b)
characters from index a up to but not including b
indexOf(str)
index of the first occurrence, or -1 if not found
equals
compares String contents
compareTo
returns a negative, zero, or positive int based on alphabetical order