Does the placing of default statement affect efficiency in Java? Is there difference between:
switch (a) {
case 0: return 0;
case 1: default: return -1;
case 2: return 2
...
case 99: return 99;
}
vs
switch (a) {
case 0: return 0;
case 1: return -1;
case 2: return 2;
...
case 99: return 99;
default: return -1;
}
Even in the most naive implementation this cannot produce a difference in performance, but with Java you are so far removed from the actual machine code this will turn into that you should definitely never even attempt to optimize this or any other similar piece of code. In fact, even if you wrote the dumbest cascade of else-ifs, you'd still stand a solid chance of JIT turning that into a superfast hash-lookup-based machine code.
No, it won't make a difference. Why? Because of this: When does the JVM know that it has to use the default body? After it checked all the other cases. So placing default: at a specific location in the which won't change performance.
I don't believe you'd see any significant performance improvements if you wrote a quick test program. At least none that would justify obscuring your code. I'd just leave the default case neatly last in the list to keep the code more readable. It's probably more important than a micro improvement in performance (if any at all)
No. The location of the switch statement makes no difference to the generated byte code other than the debugging annotations.
Related
So is this faster:
for (int i = 0; i < example.length; i++) {
switch (i) {
case 0: return example.field0;
case 1: return example.field1;
case 2: return example.field2;
case 3: return example.field3;
case 4: return example.field4;
case 5: return example.field5;
case 6: return example.field6;
case 7: return example.field7;
case 8: return example.field8;
case 9: return example.field9;
case 10: return example.field10;
}
}
Or this:
for (int i = 0; i < example.length; i++) {
return example.class.getField("field" + i);
}
I just want to know because it seems a bit tedious doing the first one and I do not want to repeat lots of lines of code that are basically doing the exact same thing.
What exactly is field0...field10? Depending on the relation between these fields, you might want to organize them in an appropriate data structure.
Do you have 11 fields of the same type and (besides their index) the same meaning, like the x-coordinates of the points of a line. Then an Array or a List might be the correct data structure.
Do these 11 fields cover the same aspect of the object and could be considered to belong together but can be named individually, like e.g. metadata of a document. The you might use a map (as "Hovercraft Full Of Eels" suggests) or put them into their own object. If you put the fields into a map, you might want to use an enumeration as key.
Are these 11 fields basically independent of each other? Then please don't try to access them together but write a getter and setter per field.
"Tedious" and "many lines of code" is not a good guide. It may be a sign of a bad design that should be corrected (see above). Otherwise there's usually a workaround in your favorite IDE. Creating setters and getters should only be a click away!
Please use reflection only if there's no other way. For examples see How could Reflection not lead to code smells?. Reflection in Java has quite a few drawbacks: bad performance, complex and difficult to get right. The main argument against reflection is IMHO that the compiler and IDEs are not made for reflection. You rename field<x> to metadata<x>? The refactoring will not change [...] getField("field" + i); and the compiler will not complain!
But to answer the actual question: Reflection is most likely a lot slower than direct Java code.
This is the code I have:
public enum Modification {
NONE, SET, REMOVE;
}
boolean foo(){
for (S s : sList) {
final Modification modification = s.getModification();
switch (modification) {
case SET:
case REMOVE:
return true;
/*
case NONE:
break;
*/
}
}
return false;
}
And when the code is as seen above, IntelliJ will say:
'for' statement does not loop less... () Reports any instance of for,
while and do statements whose bodies are guaranteed to execute at most
once. Normally, this is an indication of a bug.
Only if I make the following change, IntelliJ will be happy:
for (S s : sList) {
final Modification modification = s.getModification();
switch (modification) {
case SET:
case REMOVE:
return true;
case NONE:
break;
}
}
Why is my for loop not looping if case NONE: is not included in the switch statement?
I just tried this in eclipse and you end up with a compiler warning on the switch statement.
The enum constant NONE needs a corresponding case label in this enum switch on Modification
To resolve the warning I'm given the following options.
Add default case
Add missing case statements
Add #SuppressWarnings 'incomplete-switch' to foo()
If I add the missing case statement then the warning no longer appears. The same as adding the missing case makes your error warning disappear from intellij.
Without the statement for case NONE you can only see two cases, both of which return true. Without knowing the structure of Modification and the extra value of NONE it looks like this loop would just return true on the first iteration of the loop.
Of course the compiler should actually know that there are more values for Modification than SET and REMOVE so the warning is just for good style. Basically your code works but here's how to improve it.
I would choose to add a default statement rather than the missing case. This would be more future proof in case more values are later added to the enum. E.G.
switch (modification)
{
case SET:
case REMOVE:
return true;
default:
break;
}
Personally I'm not a fan of using the fall through on switch statements. What you gain in making the code concise you lose in legibility IMHO. If someone later comes and adds a case between SET and REMOVE it could introduce a bug. Also, having a return statement mid-way through a method can also cause problems. If someone wants to add some code just before the return they may miss all the places. If the method is very simple then multiple returns is fine but you've stated that this is a simplified example and so if this block of code is complicated I would avoid it.
If you're able to use Java 8 then this looks to be the perfect use case for the new stream API. Something like the following should work.
return sList.stream().anyMatch(
modification -> (modification==Modification.SET || modification==Modification.REMOVE)
);
i assume these are your only three cases right?, so basically its saying you are going to hit one of the first two and instantly return true, therefore not looping, just add a default case and everything should work ok, this is good practice also btw.
basically it cant see a case where it doesnt just return instantly without iterating the loop
I'd say its a false positive.
1st indication:
If you run your code through a debugger - and have elements with NONE modification in the list before an element with other modifications - it will actually loop.
2nd indication:
When you look at the generated bytecode, it transforms the switch statement to (sort of - its not exactly the same)
for (S s : sList) {
Modification modification = s.getModification();
switch (modification.ordinal()) {
case 1:
case 2:
return true;
}
}
If you put that in your code, IntelliJ does not complain.
3rd indication:
the warning dissappears if you put an additional statement before the return, i.e. System.out.println();
switch (modification) {
case SET:
case REMOVE:
System.out.println()
return true;
Seems you tricked the inspection with the missing case label and could simply ignore the warning.
I think that IntelliJ's inspections is wrong. I reported it to JetBrains
Edit : it's fixed
Your switch case always breaks or returns. In the first case, you do nothing aka it falls through. The second case returns which causes both the switch and the loop to stop. In the third case you break the switch statement which causes it to stop. It does not however stop the for loop (aka, it keeps iterating).
Either add specific functionality for the SET case or change your behaviour on the REMOVE and NONE cases.
public enum Modification {
NONE, SET, REMOVE;
}
boolean foo(){
for (S s : sList) {
final Modification modification = s.getModification();
switch (modification) {
case SET:
// This case falls through to the REMOVE case
case REMOVE:
return true; // This statement stops the switch, loop and returns true
case NONE:
break; // This statement stops the switch and continues the loop.
}
}
return false;
}
Your switch is not looping without the NONE case because return breaks the loop and returns a value from the function. break breaks the switch loop but continues the for loop.
By request of OP an extra explanation.
Falling through means the next case will be executed until a stop (break or return) is reached. This makes the following code snippets equivelant:
case SET:
case REMOVE:
return true;
is the same as:
case SET:
return true;
case REMOVE:
return true;
As answered in this question here, the scope of a variable inside of a case belongs to the entire switch statement itself, not just the case. Therefore, this does not compile (duplicate local variable):
int key = 2;
switch (key) {
case 1:
String str = "1";
return str;
case 2:
String str = "2";
return str;
}
I'm interested in mainly two things...
What's the philosophy, or design principle, behind this behavior? (Maybe I'm even asking for the motivation for the switch statement as a whole?)
How does this happen? How does this code look at the bytecode, or even assembly, level?
For better or worse, the semantics of switch in Java were heavily influenced by the semantics of switch in C. And, while we as programmers tend to think of a case label followed by some statements and a break/continue/return as a logical unit, that's not actually how it works, and no such construct exists at the language level. In a switch, break and continue are just statements, and when you execute a switch, you start at the matching case label and execute the remainder of the block. It just so happens that most of the time, you'll hit a break or continue or return before that happens. (See JLS 14.11.) The key sentence is:
All statements after the matching case label in the switch block, if any, are executed in sequence.
Many people believe (IMO, reasonably so) that the switch statement in Java has its priorities backwards; the language treats fallthrough and other control flow oddities as if they were normal case, and break as the exceptional case. But of course, in real code, it's the other way around. (How did Java acquire these backward priorities? By copying from C.)
The scoping rule for switch statements flows pretty directly from this view of the world; if the body of a switch is an undifferentiated block that happens to be peppered with case labels, of course its one big scope. Never mind that this is not actually what almost all developers want almost all the time.
In addition to confusing scoping and fallthrough-by-default, Among the other things people regret about switch in Java is that it is only a statement, not an expression. See JEP 325, which addresses all of these problems (in a backward-compatible way), which will likely be a preview features in Java 12.
Just put a pair of braces around each case clause:
int key = 2;
switch (key) {
case 1: {
String str = "1";
return str;
} case 2: {
String str = "2";
return str;
}
}
This will compile.
For example:
3 methods exist
"map1method,
map2method,
map3mehtod"
and I want to call the right one depending on what the integer 'activemap' has currently stored in it.
I could do an If statement
"If (activemap == 1)
map1method;
elseif (activemap ==2)
..."
But is there a possible way of using the integer more efficiently?
Like a "map(activemap)method"
Also could I also call a specific array in a batch of them in the same fashion.
This is all in java by the way.
It is possible via reflection but I would urge you to stay away from that approach. Why not have all three methods built into one? One option would be to use a switch statement to handle the various cases:
void mapMethod(int activemap) {
switch (activemap) {
case 1:
// map1method
break;
case 2:
// map2method
break;
case 3:
// map3method
break;
default:
break;
}
}
Now, you can call
mapMethod(activemap)
If you want to take the reflection approach instead (which as I said I don't think you should), you can do something along the lines of
String methodName = "map" + activemap + "method";
MyClass.class.getDeclaredMethod(methodName).invoke(null);
A switch statement would be slightly easier to read:
switch(activemap) {
case 1: map1method(); break;
case 2: map2method(); break;
}
You could use reflection to build the method name up at runtime, but that wouldn't be simpler. Reflection is a lot of code.
The most effective way to do this is to either create an enum to represent the different calls and use the int as a lookup for the enum value, or if that's not possible, to use a switch statement. You can use reflection to accomplish what you're talking about (look up a method at runtime based on its name), but it's less efficient and more cumbersome than either of those options.
You can do it using Reflection, It will be something like this:
java.lang.reflect.Method method;
method = myObject.getClass().getMethod("map+"activemap"+method", param1.class, param2.class, ..);
method.invoke(object, arg1, arg2,...);
We have X methods and we like call the one relative to user settings which of the following runs faster?
Case 1:
int userSetting = 1;
Method method = Class.getDeclaredMethod("Method" + userSetting);
method.invoke();
Case 2:
int userSetting = 1;
switch(userSettings) {
case 0:
Method0();
break;
case 1:
Method1();
break;
...
...
}
Case 3:
int userSetting = 1;
if(userSetting == 0){
Method0();
} else if(userSetting == 1){
Method1();
} else....
Also:
You think one even if slower is better practice that the others? If yes why?
There is another way witch is better/faster...please tell us.
Thanks
Option 1 uses reflection, and thus will probably be slower, as the javadocs indicate:
Performance Overhead
Because reflection involves types that are dynamically resolved, certain Java
virtual machine optimizations can not be performed. Consequently, reflective
operations have slower performance than their non-reflective counterparts,
and should be avoided in sections of code which are called frequently in
performance-sensitive applications.
However it is easier to maintain this option then options 2+3.
I would suggest you to use a complete different option: use the strategy design pattern. It is more likely to be faster and much more readable then the alternatives.
As amit points out, this is a case for the Strategy design pattern. Additionally, I want to give a short example:
Pseudo-Code:
public interface Calculator {
public int calc(...);
}
public class FastCalc implements Calculator {
public int calc(...) {
// Do the fast stuff here
}
}
public class SlowCalc implements Calculator {
public int calc(...) {
// Do the slow stuff here
}
}
You main program then decides which strategy to use based on the user preferences:
Calculator calc = userPreference.getBoolean("fast") ? new FastCalc() : new SlowCalc();
int result = calc.calc(...);
This is because later, you can use the Factory pattern to create multiple strategies for various operations:
Factory factory = new SlowFactory();
Calculator calc = factory.createCalculator();
Operation op = factory.createSomeOtherOperation();
Factory factory = new FastFactory();
Calculator calc = factory.createCalculator();
Operation op = factory.createSomeOtherOperation();
As you can see, the code is the same for the Slow case and for the Fast case, except the factory class, and that you can create by deciding based on the user preference. Especially if you have more such operations, such as Calculator and my Operation example, then you will want your code to not be dependent on the user preference everywhere but only at a single place.
I think the obvious slowest version is number one. reflexion is complex and is done during the runtime. for number 2 and number 3 you could have a look at Java: case-statment or if-statement efficiency perspective.
another way: could the configuration of the user change during the execution? if not, make the decision only one time on start-up.
Case 1 uses reflection and suffers a performance hit beyond approaches 2 and 3.
Between approaches 2 & 3 performance difference would be marginal at most. You must ask yourselves if any possible performance gain is really justified over code readability? Unless being on a truly limited microchip or similar I would always answer no.
Apart from the performance view, as #HoeverCraft Full Of Eels already pointed out you're probably better of redesigning your program to completely avoid the series of conditional clauses.
As all others have said #1 will most likely be the slowest.
The differences between 2 and 3 are negligible, but generally #2 shouldn't be slower than #3, because the compiler can change a switch to a cascaded if, if it thinks it would be faster. Also since the switch is clearly better readable than the if/else cascade I'd go with the second anyhow.
Although I'm extremely sure that this isn't the bottleneck anyhow - even if using reflection..