This question already has answers here:
Long list of if statements in Java
(15 answers)
Closed 7 years ago.
During recent java interview question regarding if then else was asked and question was put up in the way that if you are given with 1000 if else conditions like
if(condition 1){
task 1
}else if (condition 2){
task 2
}else if (condition 3){
task 3
}
...
else if (condition 1000){
task 1000
}
i was asked to improvise the above code . I gave the answer that it could be improvised by using switch . But interviewer was not satisfied and asked for another approach. But i was unable to explain it. So i want to know if there is any better approach to do it.
Apologies for asking such a dumb question but i really want to know answer
Thinking from the interviewer's perspective, the purpose of the question is to get an answer which would be segue to next question.
The below is one way to improve using Collection. For java interview Generics, Autoboxing would be a good segue and the following answer includes exactly that. You can improve it in various ways but the following would be an answer.
List<Integer> myRnage = new ArrayList<Integer>(1000);
for(Integer theIndex : myRnage) {
//do the task for theIndex at this point.
}
Alternatively the same can be answered with code using Apache libraries to
demonstrate the use of Range utility. Here is the SO link for that and more.
If condition is numeric comparison, you can create (or receive) a list of methods, and the index of method to be executed.
That way, you eliminate all the if and elses and simply call
methods[somePosition].Invoke()
PS:The code above isn't java, it's just an example that can be applied in any language.
use a hash table method to key into your conditions instead of checking each condition. Hashing is order 1, so it is faster than checking all conditions via if statements.
The standard method to solve such problems is using a dictionary and the Command Pattern.
This however requires to you have a simple mapping condition x -> key x which may or may not be possible depending on the use case. You can still encapsulate the condition in a more extensible way:
interface ConditionalCommand
extends Runnable
{
boolean isApplicable(conditionParams...);
}
where isApplicable() tests if the pre-conditions for running the ConditionCommand are met.
List<ConditionalCommand> commands;
The multiple ifs can then be condensed to looping over the command list:
for (ConditionalCommand cmd: commands) {
if (cmd.isApplicable(params)) {
cmd.run();
break; // or not, which allows multiple commands to be run
}
}
How the command list is obtained and stored is up to you. Commands may even be pulled from a database or similar.
Multiple if statements can be improved by switch statements sometimes, switch statements can look a bit better.
However, such things are ultimately window dressing. A long list of conditionals in code often means that there has been a design flaw. The interviewer may have been looking for a appreciation of this.
You could have suggested that the conditionals could have been replaced with polymorphism.
Consider this:
// Bad implementation that replies on condtionals
public static void Print(string animal, string quote){
switch(animal){
case "Dog":
Console.WriteLine("the dog woofed " + quote);
return;
case "Cat":
Console.WriteLine("the cat meowed " + quote);
return;
}
}
// Better implementation that pushes the detail of how animals talk into an animal object
public static void BetterPrint(Animal animal, string quote){
Console.WriteLine(animal.Speak(quote));
}
public interface IAnimal{
string Speak(string quote);
}
Through better design, conditionals have vanished. In general, in OO programming you want behavior to emerge from object interaction rather than long methods filled with switches and ifs.
The best solution depends a bit on the format of the "condition", but if it just happens that, e.g. the conditions are the integers 1 to 1000 (or more generally form a dictionary of some time), then you can form a map, of e.g. Map. Then your code reduces to
if(map.contains(condition)){
map.get(condition).doTask()
} else {
throw new Exception("Condition has no associated task")
}
which is cleaner, and it makes it easier to change the conditions.
There are many ways to do it. We can actually make it a O(1) operation. How? Using array.
class Runner(){
public static void main(String[] args){
Task[] taskList = new Task[1000];
//init taskList and fill it with tasks first
Task taskToDo = taskList[condition];
taskToDo.execute();
}
}
class Task{
public void execute(){
//code for each task
}
}
There is also something known as Command Pattern which can solve this problem as well. But implementing it with array or list works nicely as well.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
In terms of best practices, suppose I have this code:
public class ClassObject {
private int someNumber;
public void setSomeNumber(int x){
this.someNumber = x;
}
public int getSomeNumber(int x){
return this.someNumber;
}
//Should I even use this?
public void decreaseSomeNumber(){
--this.someNumber;
}
}
public void doSomeStuff(ClassObject instance){
// do some things
instance.decreaseSomeNumber(); //A
instance.setSomeNumber(instance.getSomeNumber() - 1); //B
}
I am wondering if either lines A or B are code smells. I think decreaseSomeNumber() is likely a redundant/useless function since I can just do instance.setSomeNumber(instance.getSomeNumber() - 1); everwhere.
On the other hand, it seems slightly more verbose doing instance.setSomeNumber(instance.getSomeNumber() - 1). What is the cleanest and good code design between A and B?
If you have a multithreaded environment, having (A) a decreaseSomeNumber method is worth it, however, you should make it threadsafe. Otherwise (B) two parallel threads might try to decrease the value at the same time, resulting in just a single decrease operation if they overlap.
That being said, it's typically hard work to really make code threadsafe, and in simple cases, occasional glitches might not matter. However, occasional is the keyword here: If you ever run into these, reproducing the problem will be horribly hard.
In terms of best practises you must avoid when is possible the form
public void decreaseSomeNumber(){
--this.someNumber;
}
and prefer the standard getters and setters.
But in some cases you need to decrease the value of a variable,
if this thing is occasional is good to use getters and setters
instance.setSomeNumber(instance.getSomeNumber() - 1);
instead in the case you need decreasing the a variable repeatedly (ex. A withdraw in a bank account) using only one method is not bad, but it must be defined like
public void decreaseSomeNumber(int many){
this.someNumber -= many;
}
in this way you are making a code more reusable, and this is good
P.S. the B way is more simple to syncronize in multi-threading enviroments
I would say it depends on more specific details, but I would be probably in favour of decreaseSomething.
With the getter and setter, you implicitly assume that:
The user of the API implements some (albeit trivial) computation.
The computation is performed at the time of the request.
The caller handles to concurrency-related issues on their own.
The (1) is rather a philosophical problem, although it might lead to errors caused by inadvertence, like calling get and set on two different objects.
The (2) can be a practical problem. Maybe you want to use the object from multiple threads. And maybe you don't need the number often, but you need to change it often. I believe that one could come up with some optimizations based on LongAdder or LongAccumulator or AtomicInt, which can optimize some highly concurrent places. With decreaseSomething, you can do it inside the class implementation. With getters and setters, you would need to somehow replace all occurences of x.setSomething(x.getSomething() + 1) by something else. That does not look like a proper encapsulation…
The (3) depends on your objective. Some people just make thread-unsafe code and claim it is programmer's responsibility to handle locks where needed, which can be OK. Sometimes, there might be a demand for thread-safe code. With getter and setter, you would need to use some locking scheme every time you access the data (which also makes (1) a less philosophical issue). Sometimes, it can be awful. Sometimes, it can be OK, because the caller wants to lock something more than just this one object.
As mentioned on the start of the post, I don't say I would prefer it every time. Maybe there are some cases when I would not go this way.
Edited
I would recommend changing this class as follows:
public class ClassObject {
private final int someNumber;
public ClassObject(int someNumber) {
this.someNumber = someNumber;
}
public int getSomeNumber() {
return someNumber;
}
public ClassObject decreaseSomeNumber() {
return new ClassObject(someNumber - 1);
}
public void doSomeStuff(ClassObject instance) {
//New ClassObject with new someNumber(instance's someNumber is decreased one unit)
ClassObject decreasedNumberClassObject = instance.decreaseSomeNumber();
}
}
I mean, if you wanna make a change in the Class properties(decrease, increase, multiply,...), it must return you, new Object(from the same Class), with the new property.
This code completely follows OOP paradigms. It is thread-safe, immutable and software(code) maintenance will be very high with the help of this approach.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am writing a validation function, which checks a multitude of conditions and returns Success if none of the checks fail. I want to know, what would be the preferred way among two choices and why ?
private ResponseObj validationFunc1(ObjA objA, ObjB objB, ObjC objC){
ResponseObj responseObj = new ResponseObj();
if(condA){
responseObj.setStatus("FAILURE");
responseObj.setMessage("condA message");
return responseObj;
} else if(condB){
responseObj.setStatus("FAILURE");
responseObj.setMessage("condB message");
return responseObj;
} ....
...
}else if(condZ){
responseObj.setStatus("FAILURE");
responseObj.setMessage("condZ message");
return responseObj;
}
responseObj.setStatus("SUCCESS");
responseObj.setMessage("Valid");
return responseObj;
}
private ResponseObj validationFunc2(ObjA objA, ObjB objB, ObjC objC){
if(condA){
return new ResponseObj("FAILURE","condA message");
} else if(condB){
return new ResponseObj("FAILURE","condB message");
} ....
...
}else if(condZ){
return new ResponseObj("FAILURE","condZ message");
}
return new ResponseObj("SUCCESS","Valid");
}
Which of the above 2 functions would be preferred in production code ? If so, does one method has a performance gain over another ?
Or, Am I just mistaken and the compiled code for both the functions will be same ?
Thanks in advance for your answers. If I have asked the same question again, I am very sorry. I did try my best to search for this.
Which of the above 2 functions would be preferred in production code
Neither one.
Good code follows certain rules, especially for Java, nicely formulated in the "Clean Code" book by Robert Martin. Things that clean code strongly advocates against:
high number of parameters (and 2 is consider high already ;-)
doing multiple "things" within one method/class
So, at least for some people, (well written) production code would look much different.
What you could do for example: define an interface Validator, and then put each different validation into its own class implementing that interface. And then "multiple" checks turns into instantiating each of those classes, and putting the objects in some List<Validator> ... when you then iterate, and apply one after the other.
And note: performance doesn't matter here, too. The only thing that matters is how easy to read, understand, and maintain your code is. At least for me, the above ... isn't very good at that, for the reasons stated above.
Performance should be the same. You're making the same amount of comparisons and object creations in both cases.
Approach 1 is generally easier to trace later, especially in complicated functions. At the same time, something like
if (condition) {
// lots of code
// that scrolls and scrolls
// with its own fors and ifs and whiles
} else {
// by the time you're here, you've no idea what the corresponding if() was
}
can often be replaced with
if (!condition) {
return "error";
}
// lots and lots of code
and become more readable in the process. To summarize, there is not really a right answer, use your judgement and pick the variant you feel is easier to understand
The second example probably performs better because it has less method calls. However, it is so negligible that you really need to stop caring about it.
More importantly, the second example is more readable and less prone to bugs. For the first example, you have to worry about where responseObj came from and how corrupted its state may already be before you even get to it.
To review your sample.
Always prefer immutability, so your second approach would be
better.
Returning early the code easy to follow so you don't have to
scroll all the way down.
Returning a new
ResponseObj("SUCCESS","Valid") is not a good structure cause it
would open the gate to be (incorrectly) create a new
ResponseObj("SUCCESS","Failure"). I'd suggest replacing it by an
enum with both fields, which would also make the check for success
easier downstream.
Keep it easy with the args as already pointed out
2nd approach is better, because in 1st approach code is tightly coupled and have repeated lines.
1) For tightly coupled:
If the class provider ResponseObj is third person if they renamed the data members and their respective setters and getters then you also have to change where ever you have implemented.
2) Repeated lines of code:
responseObj.setStatus("FAILURE"); there are so much same lines of code which we can see in every condition, and we dont know how many goes with number of conditions.
Solution: I feel 2nd Apparoach is better, however every thread should create a new object and constructors can be create any numbers as per the required(Overloading) without impacting to existing implemented developers.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I've stumbled across both of these methods however I can't decide which one to ultimately go for.
public void myMethod() {
if(isTrue())
return;
// code...
}
Vs.
public void myMethod() {
if(!isTrue()) {
// code...
}
}
Anyone got some exciting news as to which is better practice? I'm just curious as to how people approach this.
Taking a look at Invert "if" statement to reduce nesting explains the readability, however Java != C#, is there any difference?
Dear Karl for readbility and complexity reasons I would say the first way is better:
the first option is more clear, it avoids to have a method that is two level of indentation when there are not other statues: isTrue() is the condition of return, and should highlighted instead of having to read the whole method code.
with the first option, in general, the ciclomatic complexity (https://en.wikipedia.org/wiki/Cyclomatic_complexity) is lower, epecially if you have a lot of code in the if clause.
having an if with negation and then 'isTrue' is less clear than without the negation. It's simpler to understand.
I would prefer the second one, the reason being, we are focusing on the actual business logic. It also comes with the pre-requisites that are required to make sure our application works as expected.
public void myMethod() {
if(!isTrue()) {
// code...
}
}
Saying this I don't mean the the first way is not a got practice. Instead you can say we can log / follow the end-users flow, how they use the application, what are the trends and where they usually go. This also eases code readability.
public void myMethod() {
if(isTrue())
return;
// code...
}
Coming to the memory management, it does not really matter to JVM as both is ideally going to take the similar execution time.
Sometimes, we may have to return something in both case - whether the condition is true or false. Then we can do something like this:
public someReturnType someMethod(){
boolean isTrue = true;
if(!isTrue){
//do something which
//you want to do when the condition is false
return;
}
//do other thing which you want to
//do if the condition is true
return;
}
And more over sometimes we return an ArrayList or a String from a method then we can do this -
public ArrayList<Client> getClient(String city){
List<Client> clients = //some query that generate ArrayList<Client>
//do something
return (null != clients ? clients : Collections.EMPTY_LIST);
//While returning 'String' then you can do something like -
//return (null != someString ? someString : "");
}
The advantage of this approach is - the code using getClient() method don't require to check against null each time it get a ArrayList<Client> from the getClinet() method.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I am wondering, mostly as an industry standard approach, or as a explicitly best practice approach how would one usually program if conditionals.
I find myself using the first approach below very often, never truly had a problem with it. But I'm still wondering when should either be used.
This is just an example to illustrate what I mean, it shouldn't be taken as the normal complexity of the comparisons usually utilized.
Example
public class Validation {
int x = 5,
y = 10,
z = 100,
a = 1;
public void compare() {
if (x < y) {
// Do Something
if (y < z) {
// Do Something
if (z < a) {
System.out.println("Whatever");
}
}
}
}
public void alternate() {
if (compareNumbers(x, y)) {
// Do something
if (compareNumbers(y, z)) {
// Do something
if (compareNumbers(z, a)) {
System.out.println("Whatever");
}
}
}
}
public boolean compareNumbers(int a, int b) {
return a < b;
}
}
Which one of those would be better practice? This being a super simple example, imagining you would normally use more complex validations.
And if 'alternate' is better, how many times would the comparison method/function have to be called for it to be better?
I am sorry if this belongs in StackExchange, I wasn't very sure of which one to post it in.
To narrow the scope to StackOverflow lets say this question applies exclusively to Java. Although a general programming view/response would be appreciated.
Extracting code to methods has several advantages:
It makes the code readable
It allows for easily changing the implementation of the method
It allows for unit testing of this specific method
If all your method does is to apply the < operator to the two arguments, I'd say none of the three reasons above apply, and that you're over-complicating things.
Just use the < method, and refactor your code once you need to apply a test with some more "meat" to it.
There are no "industry standards" for this kind of thing. For good reason.
As far as whether a < b is better that compareNumbers(a, b) ... the answer depends on the actual context.
In your example, most people would agree that a < b is better1. But this is an artificial example, and the answer could be different for other (more realistic) examples.
The same goes for all sorts of other questions about the best way to express algorithms, etc in code. It is rare for questions like this to have a single objectively correct answer. It is typically a matter of opinion ... and the context really matters.
But the bottom line is that the only real "industry standard" here is:
Use your professional knowledge, skills and judgement.
... and that means things like:
thinking about each particular problem and finding an appropriate (justifiable) solution,
considering coding effort, readability2, reliability, maintainability for your solution,
considering the economics of the situation; i.e. there is a trade-off between time spent "polishing" your code and time spent doing other things like implementing functionality, testing, writing documentation, meeting deadlines.
1 - If I have to scroll down a couple of pages to check what compareNumbers is doing, this is an impediment ... compared with an inline comparison using <. Now if there was some deeper semantic behind the comparison, then method abstraction could be a good thing, especially if there were comments in the method that explained the semantics. But in this example, compareNumbers(a, b) is less semantically meaningful than a < b.
2 - Another answer states (without supporting evidence) that abstracting code to methods improves readability. This is a gross over-simplification, and often it is demonstrably false. It is important technique ... but not always the right one.
From my personal experience I would use the original compare if I know the conditions are always going to stay the same, however I would use the alternate if there were even the slightest chance of needing to change the conditions. That way I wouldn't have to go back and replace every single condition individually.
To build upon breaking out the methods, I know your example is just that, a quick example, but rather than focus on the evaluation I would focus on the task and organize the code like this:
public void someMethodThatCares(int x, int y, int z, int a)
{
taskXY(x, y);
}
public void taskXY(int x, int y)
{
if (x < y)
{
taskYZ(y, z);
}
}
public void taskYZ(int y, int z)
{
if (y < z)
{
taskZA(z, a);
}
}
public void taskZA(int z, int a)
{
if (z < a)
{
}
}
Now you can build your dependencies as you need them, test each piece of functionality independently, maintain the logic in a clean fashion, and reuse it as needed.
Actually, I focus on the complexity of the code and the importance of that logic in my project. therefore, I might use all alternatives in the same class or even in the same method.
I would suggest reading Design Patterns by the Gang of Four for more information on how to decide. For every problem the approach would be different. For example if you needed to write multiple programs that individually checked each variable, the first program doing a less than check, the second doing a greater than check, the third doing a equals check it may make sense to use the Strategy Design Pattern for each of these cases to prevent the need to create multiple programs and using a Factory creator to decide which Strategy to use. The factory pattern could decide which one to use at run time based on user input or some other method.
I just read this thread Critical loop containing many "if" whose output is constant : How to save on condition tests?
and this one Constant embedded for loop condition optimization in C++ with gcc which are exactly what I would like to do in Java.
I have some if conditions called many times, the conditions are composed of attributes define at initialization and which won't change.
Will the Javac optimize the bytecode by removing the unused branches of the conditions avoiding to spend time testing them?
Do I have to define the attributes as final or is it useless?
Thanks for you help,
Aurélien
Java compile time optimization is pretty lacking. If you can use a switch statement it can probably do some trivial optimizations. If the number of attributes is very large then a HashMap is going to be your best bet.
I'll close by saying that this sort of thing is very very rarely a bottleneck and trying to prematurely optimize it is counterproductive. If your code is, in fact, called a lot then the JIT optimizer will do its best to make your code run faster. Just say what you want to happen and only worry about the "how" when you find that's actually worth the time to optimize it.
In OO languages, the solution is to use delegation or the command pattern instead of if/else forests.
So your attributes need to implement a common interface like IAttribute which has a method run() (or make all attributes implement Runnable).
Now you can simply call the method without any decisions in the loop:
for(....) {
attr.run();
}
It's a bit more complex if you can't add methods to your attributes. My solution in this case is using enums and an EnumMap which contains the runnables. Access to an EnumMap is almost like an array access (i.e. O(1)).
for(....) {
map.get(attr).run();
}
I don't know about Java specifics regarding this, but you might want to look into a technique called Memoization which would allow you to look up results for a function in a table instead of calling the function. Effectively, memoization makes your program "remember" results of a function for a given input.
Try replacing the if with runtime polymorphism. No, that's not as strange as you think.
If, for example you have this:
for (int i=0; i < BIG_NUMBER; i++) {
if (calculateSomeCondition()) {
frobnicate(someValue);
} else {
defrobnicate(someValue);
}
}
then replace it with this (Function taken from Guava, but can be replaced with any other fitting interface):
Function<X> f;
if (calculateSomeCondition()) {
f = new Frobnicator();
else {
f = new Defrobnicator();
}
for int (i=0; i < BIG_NUMBER; i++) {
f.apply(someValue);
}
Method calls are pretty highly optimized on most modern JVMs even (or especially) if there are only a few possible call targets.