Given the following code snippets, is there any appreciable difference?
public boolean foo(int input) {
if(input > 10) {
doStuff();
return true;
}
if(input == 0) {
doOtherStuff();
return true;
}
return false;
}
vs.
public boolean foo(int input) {
if(input > 10) {
doStuff();
return true;
} else if(input == 0) {
doOtherStuff();
return true;
} else {
return false;
}
}
Or would the single exit principle be better here with this piece of code...
public boolean foo(int input) {
boolean toBeReturned = false;
if(input > 10) {
doStuff();
toBeReturned = true;
} else if(input == 0) {
doOtherStuff();
toBeReturned = true;
}
return toBeReturned;
}
Is there any perceptible performance difference? Do you feel one is more or less maintainable/readable than the others?
With the second example you state very clearly that both conditions are mutually exclusive.
With the first one, it is not so clear, and in the (unlikely) event that an assignment to input is added between both ifs, the logic would change.
Suppose someone in the future adds input = 0 before the second if.
Of course this is unlikely to happen, but if we are talking about maintainability here, if-else says clearly that there are mutually exclusive conditions, while a bunch of ifs don't, and they are not so dependent between each other as are if-else blocks.
edit:Now that I see, in this particular example, the return clause forces the mutual exclusivity, but again, we're talking about maintainability and readability.
Anyway, about performance, if this is coded in Java you shouldn't care for performance of a couple of if blocks, if it were embedded C in a really slow hardware, maybe, but certainly not with java.
Use whatever form best describes your intent.
Do not follow the single exit principle if things are this simple, though--it just makes it more confusing.
In the first:
somebody eventually, by some strange reason and when you're not looking will add some add statement that will make this method fail under certain strange conditions, everybody ( or worst, one single person ) will spend 4 hrs. watching the source code and debugging the application to finally found there was something in the middle.
The second is definitely better, not only it prevents this scenario, but also helps to clearly state , it this or this other no more.
If all the code we write within an if where 10 lines long at most, this wouldn't matter really, but unfortunately that's not the case, there exists other programmers which by some reason think that a if body should be > 200 lines long... anyway.
I don't like the third, it forces me to look for the return variable, and it's easier to find the return keyword
About speed performance, they are ( almost ) identical. Don't worry about that.
In your last example, don't do this:
public boolean foo(int input) {
boolean toBeReturned = false;
if(input > 10) {
doStuff();
toBeReturned = true;
} else if(input == 0) {
doOtherStuff();
toBeReturned = true;
}
return toBeReturned;
}
but this (notice the use of Java's final):
public boolean foo(int input) {
final boolean toBeReturned; // no init here
if(input > 10) {
doStuff();
toBeReturned = true;
} else if(input == 0) {
doOtherStuff();
toBeReturned = true;
} else {
toBeReturned = false;
}
return toBeReturned;
}
By doing so you make your intend clear and this is a godsend for IDEs supporting "programming by intention" (there's no need to "compile" to see potential errors, even on a partial AST, a good IDE can examine incomplete source in real-time and give you instant warnings).
This way you are sure not to forget to initialize your return value. This is great if later on you decide that after all you need another condition.
I do this all the time and even moreso since I started using IntelliJ IDEA (version 4 or so, a long time ago) and this has saved me so many silly distraction mistakes...
Some people will argue that this is too much code for such a simple case but that's entirely missing the point: the point is to make the intent clear so that the code reads easily and can be easily extended later on, without accidentally forgetting to assign toBeReturned and without accidentally forgetting to return from a later clause you may add.
Otherwise, if "conciseness" was the name of the game, then I'd write:
public boolean foo(int a) {
return a > 10 ? doStuff() : a == 0 ? doOtherStuff() : false;
}
Where both doStuff and doOtherStuff would return true.
Semantically — no. Performance-wise this depends on compiler, i.e. whether it can spot that both conditions cannot be true at once. I'd bet standard Sun compiler can. Whether to use single exit principle depends on tastes. I personally hate it.
Version #1 and #2 may be faster than #3, but I suppose the performance difference is minimal. I would rather focus on readability.
Personally, I would never use version #2. Between #1 and #3, I would choose the one that yields the most readable code for the case in question. I don't like many exit points in my methods, because it makes the code hard to analyze. However, there are cases where the flow becomes clearer when we exit immediately for some special cases, and continue with the main cases.
Think of this case when the two examples won't be similar:
public boolean foo(int input) {
if (input > 10) {
// doStuff();
return true;
}
System.out.println("do some other intermediary stuff");
if (input == 0) {
// doOtherStuff();
return true;
}
return false;
}
vs.
public boolean foo(int input) {
if (input > 10) {
// doStuff();
return true;
}
//System.out.println("doing some intermediary stuff... doesn't work");
else if (input == 0) {
// doOtherStuff();
return true;
} else {
return false;
}
return false;
}
The first approach is probably more flexible, but both formulas have their use in different circumstances.
Regarding performance, I think the differences are to small to be taken in consideration, for any regular java application, coded by sane programmers :).
In your case the second if would only get called if the first if failed so it's less important here but if your first if did something and didn't return, the second if (which would then always be false) would still be tested unless it was in an else-if.
In other words, there are cases where the difference between if-else-if and if-if matters, but this isn't one of them.
Example: Try this and then try it after removing the else. You get two different outputs:
int someNumber = 1;
if(someNumber < 5)
{
someNumber += 5;
Console.WriteLine("First call.");
}
else if(someNumber >= 5)
{
Console.WriteLine("Second call.");
}
Between the first and second snippets, there's really no difference. However the third snippet is quite inefficient. Because you wait to return control of the program to the caller until the last line of code in the method, you waste processing power/memory whereas the first two code snippets return control as soon as it determines one of the conditions to be true.
Related
I want to replace nested for loops in the following code with streams:
private boolean check(St st) {
List<Co> prereqs = getCoPrereqs();
for (Co prereq : prereqs) {
List<En> stEns = st.getEns();
boolean flag = false;
for (En en : stEns) {
if (en.getCo().equals(prereq) && en.getGr() != null) {
if (en.hasPassedCo()) {
flag = true;
}
}
if (!flag)
return false;
}
}
return true;
}
The two loops and the variable flag is causing confusion. I am not sure if this can be converted to streams totally.
I have simplified your code somewhat by doing the following:
removing the boolean flag. It isn't necessary.
get the List<En> just one time outside of the Prereq loop. You can reiterate the original as often as necessary.
The major difference is to check for a false return from en.hasPassedCo() and return false immediately. Once the iterations are complete, then return true.
private boolean check(St st) {
List<Co> prereqs = getCoPrereqs();
List<En> stEns = st.getEns();
for (Co prereq : prereqs) {
for (En en : stEns) {
if (en.getCo().equals(prereq) && en.getGr() != null) {
if (!en.hasPassedCo()) {
return false;
}
}
}
}
return true;
}
I'm not certain that streams would improve this (at least not knowing more about the relationships of the fields to each other). Also, it doesn't make sense how Co relates to en.getCo. Seems to me that something like prereqs.contains(en.getCo()) would be more appropriate.
Probably, you can use nested streams with allMatch.
I'm saying "probably" because I can't be sure that the code you've proved does what expected, types name are not self-explanatory at all (names in the code matter a lot) and you have not accompanied the code with any explanations.
If I understood your code correctly, you need to validate every Co object returned by getCoPrereqs() and that entails checking each Co object against En object from a List<En> which should be extracted from the method parameter.
That's how it might look like:
private boolean check(St st){
return getCoPrereqs().stream()
.allMatch((Co prereq) -> st.getEns().stream()
.allMatch((En en) -> en.getCo().equals(prereq)
&& en.getGr() != null
&& en.hasPassedCo()
));
}
For readability reasons (to make it more easier to compare stream with loops), I've used explicitly typed lambda expressions (the common practice is to omit types for brevity and let the type inference do the job).
I'm trying to make a group of if statements, in which each if will print given some argument is true, but an else that will only print if none of the ifs were returned. I don't think an else if would work in this case.
I have some code (the colors are just as examples):
boolean any=false;
if(redStage==2)
{ any=true; System.out.print(redComplete); }
if(blueStage==2)
{ any=true; System.out.print(blueComplete); }
if(greenStage==2)
{ any=true; System.out.print(greenComplete); }
if(any==false)
System.out.print(noneComplete);
Is there anything I can do to eliminate the need for a separate boolean to check whether any of the if's arguments were true?
Edit:
(I just noticed what may be confusing. The code im using isn't actually using return. Instead, it is printing out the results, which means more than one thing can be returned.)
Since you need to processes the stages independently from one another, and more than one can be complete at the same time, your code is as good as it can be.
What follows is my answer to your original question:
You don't need the boolean. Your code is equivalent to:
if (redStage == 2) { return redComplete; }
if (blueStage == 2) { return blueComplete; }
if (greenStage == 2) { return greenComplete; }
return noneComplete;
This makes use of the fact that each if body contains an unconditional return. If this wasn't the case, you could phrase the construct like so:
if (redStage == 2) {
// redComplete
} else if (blueStage == 2) {
// blueComplete
} else if (greenStage == 2) {
// greenComplete
} else {
// noneComplete
}
Of course this is an impossible statement in java (to-date), however ideally I would like to implement it as it is at the heart of many iterations. For example the first multiple times it is called I'm doing it 650,000+ times when it is creating the ArrayList.
Unfortunately the reality is that my actual code does not have the set inside the else loop; thus it will pass over both the add and then the set commands and wasting time.
After that I have it also in another loop where it is only performing the set as the data is already created and this is multi-nested with in many others so it is a lengthy process.
ArrayList<Integer> dataColLinker = new java.util.ArrayList<Integer>();
...
...
public void setLinkerAt( int value, int rowIndex) {
...
while(rowIndex >= dataColLinker.size()) {
dataColLinker.add(value);
} else {
dataColLinker.set(rowIndex, value);
}
Any ideas or theories?
I'm unsure about speeds in java when it comes to if statements and ArrayList commands and so on
Am I missing something?
Doesn't this hypothetical code
while(rowIndex >= dataColLinker.size()) {
dataColLinker.add(value);
} else {
dataColLinker.set(rowIndex, value);
}
mean the same thing as this?
while(rowIndex >= dataColLinker.size()) {
dataColLinker.add(value);
}
dataColLinker.set(rowIndex, value);
or this?
if (rowIndex >= dataColLinker.size()) {
do {
dataColLinker.add(value);
} while(rowIndex >= dataColLinker.size());
} else {
dataColLinker.set(rowIndex, value);
}
(The latter makes more sense ... I guess). Either way, it is obvious that you can rewrite the loop so that the "else test" is not repeated inside the loop ... as I have just done.
FWIW, this is most likely a case of premature optimization. That is, you are probably wasting your time optimizing code that doesn't need to be optimized:
For all you know, the JIT compiler's optimizer may have already moved the code around so that the "else" part is no longer in the loop.
Even if it hasn't, the chances are that the particular thing you are trying to optimize is not a significant bottleneck ... even if it might be executed 600,000 times.
My advice is to forget this problem for now. Get the program working. When it is working, decide if it runs fast enough. If it doesn't then profile it, and use the profiler output to decide where it is worth spending your time optimizing.
I don't see why there is a encapsulation of a while...
Use
//Use the appropriate start and end...
for(int rowIndex = 0, e = 65536; i < e; ++i){
if(rowIndex >= dataColLinker.size()) {
dataColLinker.add(value);
} else {
dataColLinker.set(rowIndex, value);
}
}
boolean entered = false, last;
while (( entered |= last = ( condition ) )) {
// Do while
} if ( !entered ) {
// Else
}
You'r welcome.
Wrap the "set" statement to mean "set if not set" and put it naked above the while loop.
You are correct, the language does not provide what you're looking for in exactly that syntax, but that's because there are programming paradigms like the one I just suggested so you don't need the syntax you are proposing.
Java does not have this control structure.
It should be noted though, that other languages do.
Python for example, has the while-else construct.
In Java's case, you can mimic this behaviour as you have already shown:
if (rowIndex >= dataColLinker.size()) {
do {
dataColLinker.add(value);
} while(rowIndex >= dataColLinker.size());
} else {
dataColLinker.set(rowIndex, value);
}
This while else statement should only execute the else code when the condition is false, this means it will always execute it. But, there is a catch, when you use the break keyword within the while loop, the else statement should not execute.
The code that satisfies does condition is only:
boolean entered = false;
while (condition) {
entered = true; // Set it to true stright away
// While loop code
// If you want to break out of this loop
if (condition) {
entered = false;
break;
}
} if (!entered) {
// else code
}
Assuming you are coming from Python and accept this as the same thing:
def setLinkerAt(value, rowIndex):
isEnough = lambda i: return i < dataColLinker.count()
while (not isEnough(rowIndex)):
dataColLinker.append(value)
else:
dataColLinker[rowIndex] = value
The most similar I could come up with was:
public void setLinkerAt( int value, int rowIndex) {
isEnough = (i) -> { return i < dataColLine.size; }
if(isEnough()){
dataColLinker.set(rowIndex, value);
}
else while(!isEnough(rowInex)) {
dataColLinker.add(value);
}
Note the need for the logic, and the reverse logic. I'm not sure this is a great solution (duplication of the logic), but the braceless else is the closest syntax I could think of, while maintaining the same act of not executing the logic more than required.
Some time ago I came across the following construct which I have rarely seen since, though I use it relatively frequently. I use it typically when checking on a whole list of conditions are true and it prevents large levels of indentation. Essentially it uses a for loop to provide a kind of structured goto. My question is firstly whether there is better way to structure this, secondly whether people like it and thirdly whether a new keyword in java/c++ etc. such as unit { } which would only cause breaks to exit to the end of the unit would be useful and clearer.
ps I realise that it is on slip away from an infinite loop, but I think my paranoia about that has meant its never happened.
Edit: I have added some setup code for the further conditions to try to illuminate problems with chained if then elses
boolean valid = false;
// this loop never loops
for (;;)
{
if (!condition1)
break;
condition2.setup();
if (!condition2)
break;
condition3.setup();
if (!condition3)
break;
valid = true;
break;
}
if (valid) dosomething();
EDIT:
I have just discovered that in fact there is a way to structure this in java without misusing loops etc. and wondered whether this would similarily be frowned on, though I guess I have missed the boat on this one.
The restructured code looks like this.
boolean valid = false;
breakout:
{
if (!condition1)
break breakout;
condition2.setup();
if (!condition2)
break breakout;
condition3.setup();
if (!condition3)
break breakout;
valid = true;
}
if (valid) dosomething();
Now that removes the misuse of the for loop which caused a lot of the complaints, and is actually a solution I think is quite neat and is what I was looking to find originally.
I am guessing that this structure is probably not well known since no one mentioned it, people object to this as strongly?
The loop is counter-intuitive and would be questioned at code review: "Why do you need a loop if you always break on the first iteration?"
Why not use this?
boolean valid = true;
if (!condition1)
valid = false;
else if (!condition2)
valid = false;
else if (!condition3)
valid = false;
if (valid) dosomething();
You may have heard of these things modern programming languages have, called functions ;)
One of the key reasons goto is no longer used is that we can now factor code out into separate functions, and call them instead.
One way to solve your problem would be to put the code in a separate function instead, and return instead of breaking from your pseudo-loop:
void safedosomething() {
if (!condition1)
return;
condition2.setup();
if (!condition2)
return;
condition3.setup();
if (!condition3)
return;
dosomething();
}
or write helper functions (such as bool checkcondition1() { condition1.setup(); return condition1; }) which set up and then test the conditions, and use a boolean flag:
bool valid = true;
if (!checkcondition1())
valid = false;
if (!checkcondition2())
valid = false;
if (!checkcondition3())
valid = false;
if (!checkcondition4())
valid = false;
if (valid) dosomething();
or a bit more concisely:
bool valid = true;
valid &&= checkcondition1();
valid &&= checkcondition2();
valid &&= checkcondition3();
valid &&= checkcondition4();
if (valid) dosomething();
or just
if (checkcondition1()
&& checkcondition2()
&& checkcondition3()
&& checkcondition4())
dosomething();
There are plenty of ways to express this, without counterintuitive loops-that-don't-loop.
The reason for this construct is because goto is a dirty word in programming. But lets face it, you are effectively using the loop construct to do the same thing. My opinion on this is either be honest and use the goto or refactor the code.
I don't think it's the most readable way of doing it. Chained if-else if looks much better. But if you want to stick with it and don't want to be so close to an infinite loop, you could do something like this:
do
{
if (...)
break;
...
} while (false);
C++ only, unfortunately:
if ( condition1
&& (condition2.setup(), condition2)
&& (condition3.setup(), condition3) )
{
dosomething();
}
For something java compatible (but I'm still writing C++!) I would fall back to something along the lines of this. (Obviously, some context may need to be passed into CheckConditions().)
bool CheckConditions()
{
if (!condition1)
return false;
condition2.setup();
if (!condition2)
return false;
condition3.setup();
if (!condition3)
return false;
return true;
}
//...
if (CheckConditions())
{
dosomething();
}
//...
You seem concerned that evaluating condition 2 requires some setup, and you don't know where to put it. Refactor that into a separate boolean method and then use that the way almost everybody here has described. For example:
if (checkCondition1() && checkCondition2(someInput) && checkCondition3()) {
doSomething();
}
and..
private boolean checkCondition2(Object someInput) {
//setup condition 2
return condition2;
}
I think the problem with
if (condition1 && condition2 && ...)
was simply that it could become hard to read and edit if there are lots of conditions, although you could always write it like this:
if ( condition1 &&
condition2 &&
condition3 ... )
doStuff();
How about you turn the loop into a function:
bool all()
{
if (!condition1) return false;
if (!condition2) return false;
if (!condition3) return false;
....
return true;
}
Here's sort of compromise, if you want to keep the indentation as it is:
boolean valid = true; // optimistic start
if (!valid || !condition1)
valid = false;
if (!valid || !condition2)
valid = false;
if (!valid || !condition3)
valid = false;
if (valid)
doSomething();
The !valid in the first if statement is superflucious but doesn't harm, could be kept for readability. else/if is more elegant, to my opinion, but that's just an opinion.
But I really wouldn't (ab-)use the for loop and I never ever would find a cheap way to implement a pseudo-goto. There's always a better solution.
I'm not sure why you need a loop if there is a break statement at the end of the loop. Arent you just iterating once, no matter the situation?
Anyway, you'll usually find two differing opinions concerning this on SO, one being that break statements shouldn't be used at all, and one being that it depends on the situation.
I tend to fall in with the latter group, but the way that your loop works uses superfluous break statements. I'd much rather structure such a loop like this:
bool valid = true;
for(... ; .... && valid == true ; ....)
{
if (!condition1)
valid = false;
if (!condition2)
valid = false;
if (!condition3)
valid = false;
}
This allows a loop exit that I think is more elegant.
Having such a long if statement is most likely bad coding.
It makes it very hard to test, and is most likely a code smell.
If possible you should refactor to take advantage of polymorphism.
How about relocating the setup to the operator bool on the Condition class? This makes it far more readable and hides the mechanics.
class Condition
{
bool _isSet;
public:
Condition() : _isSet(false) {
}
void setup() {
_isSet = true;
}
operator bool () {
if (!_isSet) {
setup();
}
return rand() & 1;
}
};
void doSomething()
{
}
int _tmain(int argc, _TCHAR* argv[])
{
Condition cond1, cond2, cond3;
if (cond1 && cond2 && cond3) {
doSomething();
}
return 0;
}
You can take that code out to a separate function and use multiple return statements. You will likely need to refactor the long list of if statements into a separate function anyway.
bool isValid()
{
if (!condition1)
return false;
condition2.setup();
if (!condition2)
return false;
condition3.setup();
if (!condition3)
return false;
return true;
}
Then you could use it in your code:
if (isValid()) dosomething();
In my program below, I set the variable th as true in the second if statement.
I'm curious why it later returns as false.
public boolean nodeExist(TreeNode Tree, T value){
boolean th = false;
if(Tree.getValue()!= null){
if(value == Tree.getValue()){
th = true;
}else{
if(value.compareTo((T) Tree.getValue()) < 0){
nodeExist(Tree.getLeft(), value);
}else{
nodeExist(Tree.getRight(), value);
}
}
}else{
th = false;
}
return th;
}
You probably look at a recursive call which sets th to true. But when that call returns to its caller, that th is still at false, and that's then returned. You need to assign the recursive callee's result:
if(value.compareTo((T) Tree.getValue()) < 0){
th = nodeExist(Tree.getLeft(), value);
}else{
th = nodeExist(Tree.getRight(), value);
}
You already got your answer. In future, to prevent mistakes like this, it's better to just return the value right away if you can. IT'S OKAY to have multiple return; if used properly, it can read to more readable code.
public boolean nodeExist(TreeNode Tree, T value){
if (Tree.getValue() == null) return false;
if (value == Tree.getValue()) return true;
if (value.compareTo((T) Tree.getValue()) < 0) {
return nodeExist(Tree.getLeft(), value);
} else {
return nodeExist(Tree.getRight(), value);
}
}
See also
Should a function have only one return statement?
Additionally, I noticed that you used == instead of equals for object comparison (i.e. T can't be a primitive type). This is rarely correct; equals is almost always what is really intended.
See also
Difference Between Equals and ==
One more style advice, please follow naming convention for Java, where variable names start with lowercase letter, with upper case letter for internal words (so, somethingLikeThis).
Programming isn't about getting things right, it's also about getting things readable. Learn and adopt a good coding style, and follow established conventions.
In the section in which you're doing your compareTo where the th value is not set. If this conditional is met, th can never be set to true.