Answer
They have identical APIs, but StringBuffer's methods are synchronized and StringBuilder's are not, so StringBuilder is the default choice for single-threaded use (almost always) and StringBuffer only when one builder is genuinely shared across threads — which is rare and usually better solved another way. Both grow by reallocating and copying when capacity is exceeded; presizing with new StringBuilder(expectedSize) avoids repeated array copies when you're appending a large, known volume of text in a hot path.
Common mistakes
- Choosing StringBuffer for single-threaded code.
- Not pre-sizing StringBuilder for large known output.