Space complexity of adding Java Strings char by char

Multi tool use
Multi tool use


Space complexity of adding Java Strings char by char



When we have to build a Java String char by char through a loop through "addition", it can be observed that the time complexity of performing this operation is poor: it is of quadratic O(n^2) time. However, I am wondering if the space complexity of "adding" a String char-by-char through a loop is also poor.


O(n^2)



Here is a minimal example of a program which performs building a String via char-by-char addition with stopwatch timing. The results I got shown below clearly show a quadratic curve:


/**Create a String of n 'A's char-by-char.
* @param n Number of 'A's to be appended
* @return The finished string
*/
public static String appendString(int n) {
String str = "";
// Timed run starts here
long t = System.currentTimeMillis();
// String concatenation occurs here
for (int k = 0; k < n; k++)
str += "A";
t = System.currentTimeMillis() - t;
// Timed run ends
System.out.printf("%dt%dn", n, t);
return str;
}



Although I can get the time complexity of the program, I am wondering what is the space complexity of building a String char-by-char?



A detailed answer that addresses memory management is preferred. (I suspect it is also quadratic because Strings are immutable, and each time you have to allocate new memory for ever-increasing Strings)



Note: This is not a duplicate of String concatenation complexity in C++ and Java because it does not address space complexity. I am specifically asking for a detailed space complexity analysis.





Well, quadratic in the short term. But old unused strings should be garbage collected, so the memory space needed should only be proportional to the size (length) of strings one needs at any given time.
– markspace
Jul 1 at 20:47





Not linear time, linear space (memory footprint). And I'm not sure about "average" either, but in the long term, yes I'd think so.
– markspace
Jul 1 at 20:48





Obligatory reference: stackoverflow.com/questions/504103/…
– lexicore
Jul 1 at 20:51





Well in the general case it's hard to say. I've considered writing my own string class on occasion when optimization is needed, but so far I've been able to avoid it. I think "better methods" depends on the application and the use model. As a general purpose implementation, String and StringBuilder are well implemented classes.
– markspace
Jul 1 at 20:51





I think that statement may be too broad. It trips my "premature optimization" sensor. Implement code in a simple method, applying only obvious optimizations. Then performance test real running code, and optimize more only where needed. If building a string character by characters seems correct, using that method is fine.
– markspace
Jul 1 at 20:55





2 Answers
2



It uses quadratic space. Or, rather, a quadratic amount of space is allocated, because each iteration of the loop will (at least in code which the JIT doesn't do something clever with) allocate a new char array:


new char[1]
new char[2]
new char[3]
// Etc.



The reason for the quadratic time performance is copying the strings into these ever-larger arrays.





Please explain quadratic space. How is more than space for 2n+1 is needed?
– lexicore
Jul 1 at 20:54


2n+1





I wouldn't say it would ever be recommended. It might simply be an expedient choice to get something implemented.
– Andy Turner
Jul 1 at 20:55





@lexicore it will run new char[1], new char[2], new char[3] etc, to create the new string instance. Perhaps the JIT can optimize it to do things more efficiently, but that is the naive approach.
– Andy Turner
Jul 1 at 20:59


new char[1]


new char[2]


new char[3]





This isn't right, surely. Once you get into very large strings, the garbage collector will collect any of the arrays other than the biggest two. So the space requirement has to be linear, not quadratic. It will appear to be quadratic at first, of course, when the program starts.
– Dawood ibn Kareem
Jul 1 at 21:15





@DawoodibnKareem I think this depends upon whether you consider the action of the GC to be part of the semantics of this code. This is why I added the "or, rather...": quadratic space is allocated; when (or whether) that is cleaned up is beyond the control of the programmer.
– Andy Turner
Jul 1 at 21:19



Your code is quite inefficient, because there is an implicit StringBuilder being created to add a single character in your loop. This,


StringBuilder


for (int k = 0; k < n; k++)
str += "A";



is equivalent to something like


for (int k = 0; k < n; k++)
str = new StringBuilder(str).append("A").toString();



You could greatly improve space (and time) performance by using a single StringBuilder instead (and you can explicitly size it). Like,


StringBuilder


StringBuilder sb = new StringBuilder(n);
for (int k = 0; k < n; k++)
sb.append("A");
String str = sb.toString();



Or, in Java 8+, you could use a generator and limit it to n times and collect that. Like,


n


return Stream.generate(() -> "A").limit(n).collect(Collectors.joining());





The approach could be even more efficient using char cs = new char[n]; Arrays.fill(cs, 'A'); String str = new String(cs);.
– Andy Turner
Jul 1 at 21:01



char cs = new char[n]; Arrays.fill(cs, 'A'); String str = new String(cs);





To make your question on-topic, can you please state the time complexity as well? I am asking for a detailed space-complexity analysis of how Java manages memory when performing that inefficient code.
– Mulliganaceous
Jul 1 at 21:04





The time complexity is O(n) (just like your solution). The constant factors are discarded when discussing time complexity. We could reduce it to O(log n) by using longer sequences of A.
– Elliott Frisch
Jul 1 at 21:50


O(n)


O(log n)


A






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

uIP65YHnU6bNhx,ul STtWyJoQi 2xCXV8k
EbkONdCprikdgvh1VaSBp26LJ7JQcUicAqkkyqpHAilLHUK

Popular posts from this blog

Rothschild family

Cinema of Italy