I was then asked how many strings this program would generate, assuming garbage collection does not happen. My thoughts for n=3 was (7)
Strings 1 (""
) and 2 ("a"
) are the constants in the program, these are not created as part of things but are 'interned' because they are constants the compiler knows about. Read more about this at String interning on Wikipedia.
This also removes strings 5 and 7 from the count as they are the same "a"
as String #2. This leaves strings #3, #4, and #6. The answer is "3 strings are created for n = 3" using your code.
The count of n2 is obviously wrong because at n=3, this would be 9 and even by your worst case answer, that was only 7. If your non-interned strings was correct, the answer should have been 2n + 1.
So, the question of how should you do this?
Since the String is immutable, you want a mutable thing - something you can change without creating new objects. That is the StringBuilder.
The first thing to look at is the constructors. In this case we know how long the string will be, and there is a constructor StringBuilder(int capacity)
which means we allocate exactly as much as we need.
Next, "a"
doesn't need to be a String, but rather it can be a character 'a'
. This has some minor performance boosting when calling append(String)
vs append(char)
- with the append(String)
, the method needs to find out how long the String is and do some work on that. On the other hand, char
is always exactly one character long.
The code differences can be seen at StringBuilder.append(String) vs StringBuilder.append(char). Its not something to be too concerned with, but if you're trying to impress the employer it is best to use the best possible practices.
So, how does this look when you put it together?
public String foo(int n) {
StringBuilder sb = new StringBuilder(n);
for (int i = 0; i < n; i++) {
sb.append('a');
}
return sb.toString();
}
One StringBuilder and one String have been created. No extra strings needed to be interned.
Write some other simple programs in Eclipse. Install pmd and run it on the code you write. Note what it complains about and fix those things. It would have found the modification of a String with + in a loop, and if you changed that to StringBuilder, it would have maybe found the initial capacity, but it would certainly catch the difference between .append("a")
and .append('a')
I'm not entirely sure I've identified the right problem, but if I have, this may help:
We created a class called ScriptManager
which lets us add arbitrary javascript files and/or functions to the bottom of all our pages when they are rendered. Give this a try:
public class ScriptManager
{
public List<string> scripts = new List<string>();
public List<string> scriptFiles = new List<string>();
}
public static class HtmlExtensions
{
[ThreadStatic]
private static ControllerBase pageDataController;
[ThreadStatic]
private static ScriptManager pageData;
public static ScriptManager ScriptManager(this HtmlHelper html)
{
ControllerBase controller = html.ViewContext.Controller;
// This makes sure we get the top-most controller
while (controller.ControllerContext.IsChildAction)
{
controller = controller.ControllerContext.ParentActionViewContext.Controller;
}
if (pageDataController == controller)
{
// We've been here before
return pageData;
}
else
{
// Initial setup
pageDataController = controller;
pageData = new ScriptManager();
return pageData;
}
}
}
Then, at the bottom of your _Layout.cshtml
page:
@foreach (var script in Html.ScriptManager().scriptFiles.Distinct())
{
@Html.Script(script);
}
@foreach (var script in Html.ScriptManager().scripts)
{
@Html.Raw("<script type='text/javascript'>")
@Html.Raw(script)
@Html.Raw("</script>")
}
Finally, you use it in a partial view like:
@{
Html.ScriptManager().scriptFiles.Add(Url.Content("~/Scripts/jquery.blockUI.js"));
}
You lose the ability to tell the client about the scripts in the header of the page, but they will be included on all pages you use a partial view that uses the blockUI (for example).
Best Answer
The process of sharing strings in this manner is called String Interning, and yes, Javascript does it. The way in which string interning is accomplished in Javascript is an implementation detail, and it varies between different Javascript implementations.
From a performance perspective, you probably shouldn't be worrying about this unless it becomes a significant problem affecting your application that you have specifically identified with a profiling tool.