Write the method getLargeAndSmallLetters that returns a String that contains all upper- and lowercase ASCII letters in the following form (upper- and lowercase letters separated by white space, letter groups separated by comma, no comma at the end):
A a, B b, C c, D d, E e, ..., Z z
The specification of the algorithm does not bear any details about implementation specifics, i.e. the use of a StringBuilder
construct, efficiency guidelines the algorithm has to meet or any best practices regarding readability of the implementation.
My version of the algorithm that compiles and returns the desired output
public static String getLargeAndSmallLetters() {
StringBuilder builder = new StringBuilder();
for (int i = 64; i < 96; ++i) { // WRONG: hard coded
if (Character.isLetter(i)) {
String upper = Character.toString((char)i);
String lower = Character.toString((char)(i+32));
builder.append(upper + " " + lower + ", "); // WRONG: in loop
}
}
String result = builder.toString();
result = result.substring(0, result.length() - 2);
return result;
}
What my docent probably would have liked to see is a for
loop like this
for (char lower = 'a'; lower <= 'z'; ++lower) {
Character upper = Character.toUpperCase(lower);
builder.append(upper)
.append(" ")
.append(lower)
.append(", ");
}
Why would the algorithm be "academically" more correct this way? This could have been solved with simple string concatenation, too.
I first want to understand why my solution is not optimal (but correct IMO). Having a C# background and can only roughly guess reasons as of why my code is not optimal:
for
loop goes through too many iterations. I correct this in an "ugly" but correct way withif (Character.isLetter(i))
.- it's not as readable
- it casts
int
s tochar
s. Is there happening any kind of boxing/unboxing that impacts performance? - the way
String
is implemented in Java, am I creating more immutableString
s inside the string pool by using the string concatenation with the+
operator inside myfor
loop? Would usingStringBuilder
be more efficient because it internally reuses the" "
and", "
String
s more efficiently?
Now what I also would like to do is to provide an "academical argument" that proves the correctness of my answer. Here some ideas:
- The compiler optimizes my "mistakes" away and actually generates the same byte code for both the "wrong" and "correct" answer
- The JIT compiler executes the same machine code for both "correct" and "wrong" answer implementations
- Provide a mathematical proof of correctness of the algorithm
Option 3 seems the most straight forward way of proofing my answers correctness to me.
For options 1 and 2 I think I'd need to correct the for loop to for (int i = 65; i < 91; ++i)
and remove the if (Character.isLetter(i))
statement.
Any suggestions, additions, corrections to my thoughts would be greatly appreciated.