toString: Bracket-Comma Format Without a Stray Comma
Try This First
You have a linked list that holds the integers 10, 20, and 30 (in that order). What string does a correct toString return?
Reveal
[10, 20, 30]
The format is an opening bracket, each element separated by a comma and a space, and a closing bracket. No comma appears before the first element or after the last one.
What You Need To Walk In With
- The list is empty when
head == null, and the empty-list case returns the literal string"Empty List". - A non-empty list formats as
[item, item, item]: opening bracket, elements separated by", ", closing bracket. - The first element is appended bare; every subsequent element is preceded by
", ". This avoids a trailing or leading comma without any fix-up step. StringBuilderis preferred over string concatenation in a loop because repeated+creates a new object on every iteration (O(n^2) work for n nodes).- The list used in this course has no dummy head node. The
headfield points directly to the first real element, or isnullfor an empty list.
How It Works
The key insight is a two-part loop structure: handle the first node before the loop starts, then let the loop handle the rest.
public String toString() {
if (head == null) return "Empty List";
StringBuilder sb = new StringBuilder("[");
sb.append(head.data); // first element, no comma
Node<T> cur = head.next;
while (cur != null) {
sb.append(", ").append(cur.data); // separator before each remaining element
cur = cur.next;
}
sb.append("]");
return sb.toString();
}
Walking through what happens for a list [10, 20, 30]:
head -> [10] -> [20] -> [30] -> null
After "sb.append(head.data)": "[10"
cur points to [20]: "[10, 20"
cur points to [30]: "[10, 20, 30"
cur is null, loop ends: "[10, 20, 30]"
The ", " separator is always prepended to the element that comes next, so the first element never receives a leading comma and the last element never receives a trailing one.
Worked Example: Predict, Then Check
Trace the method on a single-element list containing the value 42. What does toString return?
Reveal
[42]
Because head is not null, execution enters the StringBuilder branch and appends head.data (which is 42), giving "[42". The loop body never runs because head.next is null, so cur starts as null. The method appends "]" and returns "[42]".
A Common Mistake
A very common error is to append every element with a trailing ", " inside the loop:
// Wrong
for (Node<T> cur = head; cur != null; cur = cur.next) {
sb.append(cur.data).append(", ");
}
sb.append("]");
This produces [10, 20, 30, ] for a three-element list. The trailing comma-and-space before the closing bracket fails any test that asserts the exact string. The fix is the first-element-bare pattern shown above: append the first element before the loop, then append ", " followed by each subsequent element inside the loop. (Source: Liang 10e Ch 24)
Go Deeper (optional)
The toString method above runs in O(n) time because it makes exactly one pass through the list and StringBuilder.append is O(1) amortized. If you are curious about the dummy-head alternative you will see in some textbooks, it changes how traversal starts but does not change the format logic or the comma-placement strategy. That comparison comes up later in the lane. For now, the no-dummy-head version here is the course standard.
Check Yourself
Close the notes and answer each one from memory, then reveal it. Pulling an idea back from memory is one of the strongest ways to make it stick.
Check your understanding
What does the toString method return for an empty linked list (head == null)?
Why is StringBuilder preferred over the + operator for building the result string inside a loop?
Trace this buggy method on a list [A, B, C]: for each node it appends data then “, “, then appends “]”. What is the exact return value?
In the correct first-element-bare pattern, which statement appends the separator before each element beyond the first?
A list holds exactly one element with value 7. Step through the toString method: what is the value of cur immediately after the line ‘Node<T> cur = head.next;’?