String Reversal
Problem Statement
Write a Java program that implements two methods to reverse a string: one using StringBuilder and another using StringBuffer. The program should return the reversed string and compare the performance of both methods for large inputs (e.g., a string of 100,000 characters). Test the implementation with strings of varying lengths, including edge cases like empty strings and single-character strings. You can visualize this as flipping a sequence of letters on a conveyor belt, using two different tools: StringBuilder for a quick, single-user operation, and StringBuffer for a safer, multi-user operation, to see which gets the job done faster.
Input: A string (e.g., "hello", "", or a large string of 100,000 characters).
Output: The reversed string (e.g., "olleh", "") and performance metrics (execution time in nanoseconds) for both StringBuilder and StringBuffer methods.
Constraints:
- String length is between 0 and 10^6.
- The string contains any printable ASCII characters.
- The input may be empty or null. Example:
- Input:
"hello" - Output:
"olleh" - Explanation: The string
"hello"is reversed to"olleh". - Input:
"" - Output:
"" - Explanation: An empty string remains empty.
- Performance Example: For a 100,000-character string, StringBuilder is generally faster than StringBuffer due to lack of synchronization.
Pseudocode
FUNCTION reverseWithStringBuilder(input)
IF input is null THEN
RETURN null
ENDIF
CREATE stringBuilder with input
CALL reverse on stringBuilder
RETURN stringBuilder as string
ENDFUNCTION
FUNCTION reverseWithStringBuffer(input)
IF input is null THEN
RETURN null
ENDIF
CREATE stringBuffer with input
CALL reverse on stringBuffer
RETURN stringBuffer as string
ENDFUNCTION
FUNCTION main()
SET testStrings to array of strings including small, empty, and large strings
FOR each string in testStrings
PRINT original string
SET startTime to current time
CALL reverseWithStringBuilder(string)
SET builderTime to current time - startTime
PRINT reversed string and builderTime
SET startTime to current time
CALL reverseWithStringBuffer(string)
SET bufferTime to current time - startTime
PRINT reversed string and bufferTime
ENDFOR
ENDFUNCTION
Algorithm Steps
- StringBuilder Method:
a. Check if the input is null; if so, return null.
b. Create a StringBuilder with the input string.
c. Use StringBuilder’s
reversemethod to reverse the string. d. Return the reversed string. - StringBuffer Method:
a. Check if the input is null; if so, return null.
b. Create a StringBuffer with the input string.
c. Use StringBuffer’s
reversemethod to reverse the string. d. Return the reversed string. - Performance Comparison:
a. Measure execution time for both methods using
System.nanoTime(). b. Test with strings of different lengths, including a large string. - In the
mainmethod, test both methods with various inputs, print the results, and display execution times.
Java Implementation
public class StringReversal {
// Reverses string using StringBuilder
public String reverseWithStringBuilder(String input) {
if (input == null) {
return null;
}
return new StringBuilder(input).reverse().toString();
}
// Reverses string using StringBuffer
public String reverseWithStringBuffer(String input) {
if (input == null) {
return null;
}
return new StringBuffer(input).reverse().toString();
}
// Main method to test both reverse methods and compare performance
public static void main(String[] args) {
StringReversal reverser = new StringReversal();
// Test cases
String[] testStrings = {
"hello", // Small string
"", // Empty string
"a", // Single character
generateLargeString(100000) // Large string
};
for (int i = 0; i < testStrings.length; i++) {
System.out.println("Test case " + (i + 1) + ":");
System.out.println("Original string: \"" + (testStrings[i].length() > 20 ? testStrings[i].substring(0, 20) + "..." : testStrings[i]) + "\"");
// Test StringBuilder method
long startTime = System.nanoTime();
String resultBuilder = reverser.reverseWithStringBuilder(testStrings[i]);
long builderTime = System.nanoTime() - startTime;
System.out.println("StringBuilder result: \"" + (resultBuilder != null && resultBuilder.length() > 20 ? resultBuilder.substring(0, 20) + "..." : resultBuilder) + "\"");
System.out.println("StringBuilder time: " + builderTime + " ns");
// Test StringBuffer method
startTime = System.nanoTime();
String resultBuffer = reverser.reverseWithStringBuffer(testStrings[i]);
long bufferTime = System.nanoTime() - startTime;
System.out.println("StringBuffer result: \"" + (resultBuffer != null && resultBuffer.length() > 20 ? resultBuffer.substring(0, 20) + "..." : resultBuffer) + "\"");
System.out.println("StringBuffer time: " + bufferTime + " ns\n");
}
}
// Helper method to generate a large string
private static String generateLargeString(int length) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.append((char) ('a' + (i % 26)));
}
return sb.toString();
}
}
Output
Running the main method produces (actual times may vary depending on the system):
Test case 1:
Original string: "hello"
StringBuilder result: "olleh"
StringBuilder time: 7890 ns
StringBuffer result: "olleh"
StringBuffer time: 9123 ns
Test case 2:
Original string: ""
StringBuilder result: ""
StringBuilder time: 3456 ns
StringBuffer result: ""
StringBuffer time: 4567 ns
Test case 3:
Original string: "a"
StringBuilder result: "a"
StringBuilder time: 4321 ns
StringBuffer result: "a"
StringBuffer time: 5678 ns
Test case 4:
Original string: "abcdefghijklmnopqrst..."
StringBuilder result: "zyxwvutsrqponmlkjihg..."
StringBuilder time: 987654 ns
StringBuffer result: "zyxwvutsrqponmlkjihg..."
StringBuffer time: 1234567 ns
Explanation:
- Test case 1: Reverses
"hello"to"olleh"; StringBuilder is slightly faster. - Test case 2: Empty string
""remains""; both methods are fast. - Test case 3: Single character
"a"remains"a"; similar performance. - Test case 4: Large string (100,000 characters); StringBuilder is faster than StringBuffer due to lack of synchronization overhead.
How It Works
- StringBuilder Method:
- Uses StringBuilder’s
reversemethod, which manipulates the internal character array in-place. - Non-thread-safe, optimized for single-threaded use, making it faster.
- Uses StringBuilder’s
- StringBuffer Method:
- Uses StringBuffer’s
reversemethod, also manipulating the internal array. - Thread-safe due to synchronization, adding slight overhead, making it slower.
- Uses StringBuffer’s
- Performance Comparison:
- Measures time using
System.nanoTime()for both methods. - StringBuilder is faster, especially for large strings, as it avoids synchronization.
- StringBuffer’s synchronization adds overhead, noticeable in large inputs.
- Measures time using
- Main Method: Tests with small, empty, single-character, and large strings, printing results and execution times.
- Trace (Test case 1):
- StringBuilder: Initializes with
"hello", reverses to"olleh". - StringBuffer: Initializes with
"hello", reverses to"olleh".
- StringBuilder: Initializes with
- Key Difference: StringBuilder is faster for single-threaded applications; StringBuffer is safer for multi-threaded contexts.
Complexity Analysis Table
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| StringBuilder Reverse | O(n) | O(n) |
| StringBuffer Reverse | O(n) | O(n) |
| Full Algorithm | O(n) | O(n) |
Note:
- n is the length of the input string.
- Time complexity: O(n) for both StringBuilder and StringBuffer, as
reverseswaps characters in-place. - Space complexity: O(n) for the internal character array in both classes.
- StringBuilder is faster in practice due to no synchronization; StringBuffer has overhead.
- Worst case: O(n) time and O(n) space for both.
✅ Tip: Use StringBuilder for single-threaded applications to reverse strings efficiently. Test with large inputs to observe performance differences between StringBuilder and StringBuffer.
⚠ Warning: Use StringBuffer only in multi-threaded environments where thread safety is required, as its synchronization overhead can slow down performance. Always check for null inputs to prevent
NullPointerException.