I am trying to map values from one enum to the other based on some calculation or conditional logic that I need to perform to set the correct enum value for the class variable. How can I do this without using too many if/else, switch statements?
Enum BRAND {
MINI, FERRARI, PAGANI
}
and another enum
Enum ENGINE {
LEVEL1, LEVEL2, LEVEL3
}
And I have a class like :
Class Car() {
int model;
int year;
Engine engine;
// I want to calculate set the engine depending on the brand based on conditional logic
public carEngineCalculator (Brand b) {
Car mycar = new Car();
if (mycar.isSuperCar(b) {
if (mycar.isCrazyGood(b)) {
mycar.engine = ENGINE.LEVEL1;
} else {
mycar.engine = ENGINE.LEVEL2;
}
} else {
mycar.engine = ENGINE.LEVEL3;
}
... //And the conditions can be more complex
}
public boolean isSuperCar(Brand b) {
if (b.FERRARI || b.PAGANI) {
return true;
}
return false;
}
public boolean isCrazyGood(Brand b) {
return ...;
}
}
There can be more than one such conditions that need to be checked in order to set the values and I want to avoid nasty if/else/switch statements as shown above. Is there a more functional way of doing this.
Using predicates as I said would look like this:
public enum Brand {
MINI,
FERRARI,
PAGANI
}
public enum Engine {
LEVEL1,
LEVEL2,
LEVEL3
}
public class Entry {
public final Predicate<Car> pred;
public final Engine engine;
public Entry(Predicate<Car> pred, Engine engine) {
this.pred = pred;
this.engine = engine;
}
}
public class Car {
int model;
int year;
Engine engine;
public void carEngineCalculator(Brand b) {
Car mycar = new Car();
List<Entry> cases = new ArrayList<>();
cases.add(new Entry(c -> c.isSuperCar(b) && c.isCrazyGood(b), Engine.LEVEL1));
cases.add(new Entry(c -> c.isSuperCar(b) && !c.isCrazyGood(b), Engine.LEVEL2));
cases.add(new Entry(c -> !c.isSuperCar(b), Engine.LEVEL3));
mycar.engine = cases.stream().filter(x -> x.pred.test(mycar)).findFirst().get().engine;
}
public boolean isSuperCar(Brand b) {
if ((b == Brand.FERRARI) || (b == Brand.PAGANI)) {
return true;
}
return false;
}
public boolean isCrazyGood(Brand b) {
return false;
}
}
You create a List with Predicates and Results and use stream, filter and findFirst to go through the list and find the right result. If the conditions are simpler than you don't need predicates and test it a little bit different.
If the mapping is one-to-one for Brand and Engine, you could do something like this:
enum Brand {
MINI(Engine.LEVEL1),
FERRARI(Engine.LEVEL2),
PAGANI(Engine.LEVEL3);
private final Engine engine;
private Brand(Engine engine) {
this.engine = engine;
}
public final Engine getEngine() {
return engine;
}
}
Another option:
enum Brand {
MINI(false, false),
FERRARI(true, true),
PAGANI(false, true);
private final boolean superCar;
private final boolean crazyGood;
private Brand(boolean superCar, boolean crazyGood) {
this.superCar = superCar;
this.crazyGood = crazyGood;
}
public final Engine getEngine() {
if (superCar) {
return (crazyGood) ? Engine.LEVEL1 : Engine.LEVEL2;
}
return Engine.LEVEL3;
}
}
If the mapping is not one-to-one and you need to somehow dynamically calculate the engine based on some parameters, you could also use this:
enum Brand {
MINI {
@Override
public Engine getEngine(boolean superCar, boolean crazyGood) {
return (superCar && crazyGood) ? Engine.LEVEL1 : Engine.LEVEL2;
}
},
FERRARI {
@Override
public Engine getEngine(boolean superCar, boolean crazyGood) {
return superCar ? Engine.LEVEL1 : Engine.LEVEL3;
}
},
PAGANI {
@Override
public Engine getEngine(boolean superCar, boolean crazyGood) {
return Engine.LEVEL3;
}
};
public abstract Engine getEngine(boolean superCar, boolean crazyGood);
}
Or something like this, where you have some defaults and override just for special cases:
enum Brand {
MINI,
FERRARI {
@Override
public Engine getEngine(boolean superCar, boolean crazyGood) {
return superCar ? Engine.LEVEL1 : Engine.LEVEL3;
}
},
PAGANI;
public Engine getEngine(boolean superCar, boolean crazyGood) {
return Engine.LEVEL3;
}
}
There are a lot of possibilities using just enums, which I actually prefer to complex if/else or switch statements. Of course it depends on what exactly you want to do and since there is not much info provided, I cannot really give the best answer. Hope that this helps you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With