StringBuilder Capacity Management
Problem Statement
Write a Java program that demonstrates StringBuilder’s capacity resizing by appending strings and monitoring capacity changes using the capacity() method. The program should analyze when resizing occurs and how the capacity adjusts based on the appended content. Test the implementation with different scenarios, including appending small strings, large strings, and using StringBuilder instances with varying initial capacities. You can visualize this as filling a stretchable notebook, where the notebook expands its pages (capacity) automatically when you add more notes, and you track how and when it grows to accommodate the text.
Input: A series of strings to append to StringBuilder instances with different initial configurations (e.g., default capacity, specified initial capacity). Output: The final string, a log of capacity changes after each append operation, and an analysis of when resizing occurs. Constraints:
- String lengths are between 0 and 10^5.
- Strings contain printable ASCII characters.
- Initial capacities are non-negative integers.
- The input strings may be null or empty. Example:
- Input: Append
"hello"," world"to a StringBuilder with default capacity (16). - Output:
Initial capacity: 16 After appending "hello": length=5, capacity=16 After appending " world": length=11, capacity=16 Final string: "hello world" - Explanation: No resizing occurs as the total length (11) fits within the initial capacity (16).
- Input: Append a 20-character string to a StringBuilder with default capacity (16).
- Output:
Initial capacity: 16 After appending: length=20, capacity=34 Final string: "abcdefghijklmnopqrst" - Explanation: Resizing occurs because 20 exceeds 16, new capacity = (16 * 2) + 2 = 34.
Pseudocode
FUNCTION demonstrateCapacityManagement(testCases)
FOR each testCase in testCases
SET initialCapacity to testCase.initialCapacity
SET strings to testCase.strings
CREATE stringBuilder with initialCapacity
PRINT initial capacity
FOR each string in strings
SET oldCapacity to stringBuilder.capacity()
APPEND string to stringBuilder
SET newCapacity to stringBuilder.capacity()
PRINT length, capacity, and whether resizing occurred
ENDFOR
PRINT final string
ENDFOR
ENDFUNCTION
FUNCTION main()
SET testCases to array of (initialCapacity, strings) pairs
CALL demonstrateCapacityManagement(testCases)
ENDFUNCTION
Algorithm Steps
- Define a method to demonstrate capacity management:
a. For each test case, create a StringBuilder with the specified initial capacity.
b. Print the initial capacity using
capacity(). c. For each string to append:- Record the current capacity.
- Append the string using
StringBuilder.append. - Check the new capacity and note if resizing occurred (capacity increased).
- Print the current length, capacity, and resizing status. d. Print the final string.
- Handle null or empty strings by skipping or appending empty content.
- In the
mainmethod, test with different scenarios:- Default capacity (16) with small strings.
- Default capacity with a large string that triggers resizing.
- Custom initial capacity with multiple appends.
- Empty or null strings.
- Analyze resizing: StringBuilder doubles the current capacity and adds 2 when the length exceeds the capacity.
Java Implementation
public class StringBuilderCapacityManagement {
// Demonstrates StringBuilder capacity resizing
public void demonstrateCapacityManagement(String[][] testCases, int[] initialCapacities) {
for (int i = 0; i < testCases.length; i++) {
String[] strings = testCases[i];
int initialCapacity = initialCapacities[i];
System.out.println("Test case " + (i + 1) + ":");
System.out.println("Initial capacity: " + initialCapacity);
StringBuilder sb = new StringBuilder(initialCapacity);
for (int j = 0; j < strings.length; j++) {
String str = strings[j] != null ? strings[j] : "";
int oldCapacity = sb.capacity();
sb.append(str);
int newCapacity = sb.capacity();
System.out.println("After appending \"" + (str.length() > 20 ? str.substring(0, 20) + "..." : str) + "\": " +
"length=" + sb.length() + ", capacity=" + newCapacity +
(newCapacity > oldCapacity ? " (resized)" : ""));
}
System.out.println("Final string: \"" + (sb.length() > 50 ? sb.substring(0, 50) + "..." : sb.toString()) + "\"\n");
}
}
// Main method to test capacity management
public static void main(String[] args) {
StringBuilderCapacityManagement manager = new StringBuilderCapacityManagement();
// Test cases
String[][] testCases = {
{"hello", " world"}, // Small strings, default capacity
{generateLargeString(20)}, // Large string, triggers resizing
{"a", "b", "c", "d"}, // Multiple small strings, custom capacity
{""}, // Empty string
{null} // Null string
};
int[] initialCapacities = {16, 16, 5, 16, 16}; // Corresponding initial capacities
manager.demonstrateCapacityManagement(testCases, initialCapacities);
}
// 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 capacities may vary slightly depending on JVM implementation):
Test case 1:
Initial capacity: 16
After appending "hello": length=5, capacity=16
After appending " world": length=11, capacity=16
Final string: "hello world"
Test case 2:
Initial capacity: 16
After appending "abcdefghijklmnopqrst...": length=20, capacity=34 (resized)
Final string: "abcdefghijklmnopqrst"
Test case 3:
Initial capacity: 5
After appending "a": length=1, capacity=5
After appending "b": length=2, capacity=5
After appending "c": length=3, capacity=5
After appending "d": length=4, capacity=5
Final string: "abcd"
Test case 4:
Initial capacity: 16
After appending "": length=0, capacity=16
Final string: ""
Test case 5:
Initial capacity: 16
After appending "": length=0, capacity=16
Final string: ""
Explanation:
- Test case 1: Appends
"hello"," world". Length (11) < capacity (16), no resizing. - Test case 2: Appends 20-character string. Length (20) > 16, resizes to (16 * 2) + 2 = 34.
- Test case 3: Custom capacity 5, appends four single characters. Length (4) ≤ 5, no resizing.
- Test case 4: Empty string, no change in length or capacity.
- Test case 5: Null string treated as empty, no change.
How It Works
- StringBuilder Capacity: Represents the size of the internal character array. Default is 16 if not specified.
- Resizing: When the length exceeds capacity, StringBuilder allocates a new array with capacity = (oldCapacity * 2) + 2.
- demonstrateCapacityManagement:
- Creates StringBuilder with specified initial capacity.
- Tracks capacity before and after each append.
- Reports resizing when new capacity exceeds old capacity.
- Example Trace (Test case 2):
- Initial:
capacity = 16,length = 0. - Append
"abcdefghijklmnopqrst"(20 chars):length = 20> 16, new capacity = (16 * 2) + 2 = 34.
- Initial:
- Main Method: Tests with small strings, large strings triggering resizing, custom capacity, and edge cases.
- Analysis: Resizing occurs when the total length after appending exceeds the current capacity, doubling the capacity plus 2 to accommodate future appends efficiently.
Complexity Analysis Table
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Append | O(m) | O(m) |
| Capacity Check | O(1) | O(1) |
| Resizing | O(n) | O(n) |
| Full Algorithm | O(k * m) | O(n + k * m) |
Note:
- n is the current length of the StringBuilder, m is the length of the appended string, k is the number of append operations.
- Append: O(m) for copying characters, amortized O(1) if no resizing.
- Resizing: O(n) when copying the internal array to a larger one.
- Full algorithm: O(k * m) time for k appends, O(n + k * m) space for the final StringBuilder content.
- Worst case: Frequent resizing for large strings increases time and space.
✅ Tip: Set an appropriate initial capacity for StringBuilder when the expected size is known to minimize resizing. Use
capacity()to monitor and understand resizing behavior during development.
⚠ Warning: Avoid unnecessarily small initial capacities, as frequent resizing can degrade performance. Handle null inputs to prevent unexpected behavior during append operations.