Usually, in problems that I encounter in school, there are ones that the expects us to use switch cases. Though I always use arrays as alternative for this kind of problem for the sake of shorter codes.
So a solution with Switch-Statement will look like this:
String day;
int dayNum = n%7; //n is an input
switch(dayNum){
case 0:
day = "Sunday";
break;
case 1:
day = "Monday";
break;
case 2:
day = "Tuesday";
break;
case 3:
day = "Wednesday";
break;
case 4:
day = "Thursday";
break;
case 5:
day = "Friday";
break;
case 6:
day = "Saturday";
break;
}
System.out.println("Today is " day);
And a solution with array as alternative for this looks like this:
int dayNum = n%7; //n is an input
String[] day = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
System.out.println("Today is " day[dayNum]);
The second example is the kind of code I usually prefer to use.
What I'd like to ask is how does the 2 solutions compare when it comes to memory and time complexity?
CodePudding user response:
The code you wrote is just bad use of switches.
switches are great when one, or preferably both, of these things holds:
- The values you are triggering on aren't consecutive (i.e.
case 384:
, thencase 30491:
, etcetera. Trivial example is when switching on a string for a certain command. - The thing you want to do is a bunch of code (vs. returning a single result, as here).
For what its worth, you've also written the case block in a rather convoluted fashion. If you have a separate method for this, you could write:
switch (foo) {
case 0: return "Sunday";
case 1: return "Monday";
}
Also (new in.. java 14?), you can write this too:
String dayName = switch(foo) {
case 0 -> "Sunday";
case 1 -> "Monday";
default -> throw new IllegalArgumentException("Unknown day");
};
Lastly, this code should not exist. Because java.time.DayOfWeek
already exists. You've badly reinvented the wheel.
Performance
When talking about 7 elements it just doesn't matter. Other factors dominate, simple as that.
As a general principle (which doesn't kick in until many many hundreds, maybe thousands, see footnote!), the reason your array-based code is linear as you wrote it is solely because java would not (currently; future java changes are afoot that may change this) realize that the line that 'makes' your string array with day names can be executed once for the lifetime of a JVM boot and never again; in other words, this code, under the hood, compiles down to making a new string array with 7 slots and then assigning 7 constants to the slots (those constants are the references to the strings, which are calculated "once per VM lifetime").
If you move that array into a static field, that goes away and they're both O(1)
performance (the same 'speed' whether you have 7 days or 7 million days), because they both just do a single lookup. No looping.
IMPORTANT PERFORMANCE FOOTNOTE: Computers are incredibly complex and act nothing like a von neumann model. Predicting the performance of code based on common sense therefore usually steers you extremely wrong. There are therefore 3 important rules to keep in mind:
Write code the way java programmers the world over tend to write it, and keep things flexible. IF performance issues occur, you will probably need to change the relevant part of your app. This is easier if your code is flexible. Most rules of thumb about performance you read about make your code less flexible and are therefore bad! - also, the JVM optimizes code, and does this essentially by being a giant pattern matching machine, detecting patterns it knows how to run well. The programmers who make this pattern matching optimizing machine tend to write patterns that are commonly used in java code. Thus, idiomatic java code tends to be fast in practice.
Nobody can look at code and just know how it ends up performing in real life, because it's too complex. Don't take my word for it; the very engineers that write the VM say this all the time. If they can't figure it out, you stand no chance whatsoever. Therefore, a profiler report or JMH timing result is required before even thinking about letting code performance ideas determine how you write your code. See the rule above: Without this, the best, fastest code is the cleanest, most flexible, most easy to read code.
The one exception is algorithmic complexity (big O notation). This is a complex topic (generally, university-level informatics and very math heavy), well beyond an SO answer, but plenty of online resources can be found if you want to dive in. But do note that the big-O factor often doesn't start controlling until you get a ton of data. For example, in this case technically your array-based code is
O(n)
(because you create the array inside the code, every time you run it), whereas the switch isO(1)
, but given that n is 7 here, that's irrelevant. It probably won't get relevant until you get to hundreds of items.