Reduce the number of variables used in my if-else statements
I know it sounds terrible but in my java program I have about 100 if-else statements, all containing 3 variables that have to stay unique to those if-else blocks, 1 is a flag used to know when its the first time ever hitting that if-else block, and the other 2 are both strings and are temp variables holding that data that was used last time it ran through that if-else block, so it can be compared to the data running through this time around, sorry if it sounds sloppy, I hate the idea of having so many if-else blocks, but right now Im more concerned about the variables, because if I make 3 variables for each block that is an extra 300 variables. Any suggestions on something I could implement to reduce the amount of variables, one idea I have was 1 array for all the flags and then a 2d array holding the 2 strings for each if-else block. Thanks Beef.
Edited: to show sample of the first 2 if-else blocks, all the other have the same code inside just wit开发者_StackOverflowh different names for the flag and temp variables ex. ac101Flag, tempAC101Start, tempAC101End
// AC 101
if (room.equals("FEB 2009") || room.equals("FEB 2011") ||room.equals("FEB 2013") || room.equals("FEB 2015") || room.equals("FEB 2017") ||
room.equals("FEB 2021") || room.equals("FEB 2023") || room.equals("FEB 2025") || room.equals("FEB 2027") || room.equals("FEB 2029")) {
instanceNum = 4;
devID = 130200;
if (ac101Flag == false) {
Delete();
Insert();
ac101Flag = true;
tempAC101Start = Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'));
tempAC101End = Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'));
}
//Insert();
else if (tempAC101Start <= (Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'))) && tempAC101End >= Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'))) {
}
else
{
Insert();
tempAC101Start = Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'));
tempAC101End = Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'));
}
}
// AC 102
else if(room.equals("FEB 1130")) {
instanceNum = 4;
devID = 130400;
if (ac102Flag == false) {
Delete();
Insert();
ac102Flag = true;
tempAC101Start = Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'));
tempAC101End = Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'));
}
//Insert();
else if (tempAC101Start <= (Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'))) && tempAC101End >= Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'))) {
}
else
{
Insert();
tempAC101Start = Double.parseDouble(finalStart.substring(0, 5).replace(':', '.'));
tempAC101End = Double.parseDouble(finalEnd.substring(0, 5).replace(':', '.'));
}
}
EDIT: Just to give a more concrete demonstration of the answer, I think you want something like:
class Foo // Rename this!
{
private double start;
private double end;
private boolean flag;
public void handleValue(double newStart, double newEnd)
{
// Insert code here
}
}
private static void insertFoo(Map<String, Foo> map, String... rooms)
{
Foo foo = new Foo();
for (String room : rooms)
{
map.put(room, foo);
}
}
...
HashMap<String, Foo> map = new HashMap<String, Foo>();
insertFoo(map, "FEB 2009", "FEB 2011", ...);
insertFoo(map, "FEB 1130");
Then in your loop, just use:
Foo foo = map.get(room);
foo.update(start, end); // Parsed from the current finalStart/finalEnd
It's hard to say for sure without seeing your code, but it sounds like you should encapsulate all of this in a data structure:
- The three variables (state and falg)
- "Something" to represent the condition of the
if
part. The exact nature of this will depend on what you've got
You can then run through a list of these ConditionBlock
objects (or whatever you choose to call them) and check whether the block "matches" in the current context, updating it where appropriate.
If you can give us a small example of the original code, we can probably refactor it for you fairly easily.
EDIT: As I apparently haven't been clear about introducing the local variables for the sake of parsing in one place, I'd do something like this (as one first step):
// TODO: Don't use double here - it's completely inappropriate. Use
// BigDecimal if you absolutely must, but preferrably use a time-related
// type, e.g. something from Joda Time (http://joda-time.sf.net)
double parsedStart = Double.parseDouble(finalStart.substring(0, 5)
.replace(':', '.'));
// TODO: Put all of these constants in a HashSet<String> and use contains
if (room.equals("FEB 2009") ||
room.equals("FEB 2011") ||
room.equals("FEB 2013") ||
room.equals("FEB 2015") ||
room.equals("FEB 2017") ||
room.equals("FEB 2021") ||
room.equals("FEB 2023") ||
room.equals("FEB 2025") ||
room.equals("FEB 2027") ||
room.equals("FEB 2029")) {
instanceNum = 4;
devID = 130200;
// TODO: Change to if (!ac101Flag)
if (ac101Flag == false) {
// TODO: Rename these methods to follow Java naming conventions
Delete();
Insert();
ac101Flag = true;
tempAC101Start = parsedStart;
tempAC101End = parsedEnd;
}
//Insert();
else if (tempAC101Start <= parsedStart && tempAC101End >= parsedEnd) {
}
else
{
Insert();
tempAC101Start = parsedStart;
tempAC101End = parsedEnd;
}
}
The one issue that was not clear in your question was how similar the if blocks are, In any case you might have an if block ancestor class with a common inteface and adopting the ideas above, create an instance for each if block, with the state variables as part of the object, then create a collection of those objects and then just loop through the collection of if blocks calling each in turn. Each if-block instance would inherit the common variable and be unique to the object (encapsulation) and each block could have tailored code for each special case for each if block.
The code overhead for defining each instance would be greater and the execution time would be more but you would not have to create seperate variables and you would mix and match and change order of the if blocks dynamically if you wanted to.
Declare a class that has the three fields. Create an array of this class for the number of instances that you need to maintain.
private class Vars{
int val1;
String val2, val3;
}
private Vars[] allVars = new Vars[300];
void myMethod(){
if (condition1){
allVals[0].val1 = ...;
}
}
Consider using polymorphism.
Each block has behavior and data. So make each block an object that implements an interface.
Each block object can hold onto a state object like @Jon Skeet suggests.
First, pick an object. That might be with your existing if statements, or if possible, via some simpler mapping.
Then, just call the method on the object you've picked.
class BlockState {
boolean hasBeenCalled = false;
String last1;
String last2;
}
class Block1 implements Runnable {
BlockState m_blockState = new BlockState();
public void run() { ... }
}
...
class BlockN implements Runnable {
BlockState m_blockState = new BlockState();
public void run() { ... }
}
...
class LongChainOfIfs
void foo() {
Runnable runnable = null;
if ( ... ) runnable = ...
else if ( ... ) runnable = ...
...
else runnable = ...
runnable.run();
}
}
精彩评论