What is the most efficient algorithm for reversing a String in Java?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The most efficient way to reverse a string in Java is new StringBuilder(str).reverse().toString(). It runs in O(n) time and O(n) space, correctly handles Unicode surrogate pairs, and is optimized at the JVM level. For character arrays, an in-place two-pointer swap is the fastest approach with O(1) extra space. Avoid string concatenation in a loop (result += str.charAt(i)) — it creates a new String object on every iteration, making it O(n^2).
Method 1: StringBuilder.reverse() (Recommended)
StringBuilder.reverse() is implemented in native code, handles surrogate pairs correctly, and operates in a single pass over the internal character array.
Method 2: char Array with Two-Pointer Swap
The most memory-efficient approach — O(1) extra space beyond the array:
This is O(n) time and swaps characters in place without any extra data structures.
Method 3: StringBuilder Manual Append
Setting the initial capacity with new StringBuilder(str.length()) avoids internal array resizing.
Method 4: Recursion
This is O(n^2) due to string concatenation and substring creating new strings at each level. It also risks StackOverflowError for long strings. Use only for educational purposes.
Method 5: Java 8+ Streams
Streams add significant overhead for this operation. StringBuilder.reverse() is simpler and faster.
Handling Unicode Surrogate Pairs
Characters outside the Basic Multilingual Plane (like emojis) use two char values (a surrogate pair). The two-pointer swap can corrupt them:
If you use the two-pointer approach, check for surrogates:
Performance Comparison
| Method | Time | Space | Surrogate-Safe |
StringBuilder.reverse() | O(n) | O(n) | Yes |
| char[] two-pointer | O(n) | O(n) for result | No |
| codePoints two-pointer | O(n) | O(n) | Yes |
| StringBuilder manual append | O(n) | O(n) | No |
| String concatenation loop | O(n^2) | O(n^2) | No |
| Recursion | O(n^2) | O(n) stack | No |
Common Pitfalls
- Using string concatenation in a loop:
result = str.charAt(i) + resultorresult += str.charAt(i)creates a newStringobject on every iteration because strings are immutable in Java. For a 10,000-character string, this creates 10,000 intermediate string objects and is O(n^2). - Not handling surrogate pairs: Characters like emojis (🌍, 😀) are represented as two
charvalues in Java. A naive character-by-character reverse corrupts these pairs. UseStringBuilder.reverse()orcodePoints()to handle them correctly. - Using recursion for long strings: Each recursive call adds a stack frame. For strings longer than a few thousand characters, the recursive approach throws
StackOverflowError. The default stack depth in Java is roughly 5,000-10,000 frames. - Not preallocating StringBuilder capacity:
new StringBuilder()starts with capacity 16. For a long string, the internal array resizes multiple times (doubling each time). Pass the expected length:new StringBuilder(str.length()). - Using
StringBufferinstead ofStringBuilder:StringBufferis thread-safe (synchronized), which adds overhead. In single-threaded contexts (most string reversals),StringBuilderis faster. UseStringBufferonly when multiple threads modify the same buffer.
Summary
- Use
new StringBuilder(str).reverse().toString()for the fastest, simplest, and surrogate-safe reversal - Use the char array two-pointer swap for minimal memory overhead (but handle surrogates separately)
- Never use string concatenation in a loop — it is O(n^2)
- Preallocate
StringBuildercapacity when building strings manually - Prefer
StringBuilderoverStringBufferunless thread safety is required

