For the past three days, and probably for the next three weeks, I am cleaning code. This is usually a good thing, since code is like your room: It collects random bits and pieces that seemed important at the time, but now you look at and go “what does this thingy do? ” and “Do I really need three of these things?’ Not to mention the fact that clattared code, like a clattered room, is ungainly and makes hard to find what you’re looking for.
Sometimes, though, you find things that you weren’t looking for. Like this fun little example:
String letters; for (i=65;i<=91;i++) letters+=String.valueOf((char)i);
This little doohickey seems fairly straight forward, doesn’t it? It goes through the letters of the alphabet and produces a string of all the letters one after the other. With a total length of 26 characters (208 bytes.) Nice, simple, effiecent code. Right?
Wrong. Java strings are immutable. Once created, they never, ever change. So that means that the concatenation operator “+=” doesn’t just add another character to the existing string – it creates a whole new one. The old string doesn’t go away (At least not right away. It will get caught in the garbage collector eventually) so instead of having one string “letters” you have this:
A AB ABC<-letters
A AB ABC ABCD <-letters
And so on. “letters” always points to the last string created, and eventually the rest of the strings will go away. But a quick calculation shows that in the meantime they take up a combines total of 351 chars. About 2.5 Kilobytes of space. Granted, that’s not much nowadays. But imagine you had this in a loop that ran to 10000? Now we’re talking 40MB of memory (instead of 78k) That’s a bit more of a problem. Make your string increment by two characters at a time instead of one, and we’re up to 193MB (instead of roughly 156k) That’s substantial. Even by today’s standards.
What’s surprising is how often I see things like this in actual code. Not just in our project, but also in other open-source projects and code samples on line. Particularly since this is easy to avoid (use a StringBuffer or StringBuilder). It’s one of those little pitfalls of Java that it seems not all that many people are aware of.