Reputation: 109
I am a beginner to Java and I have a health insurance program, which returns a total quote based on if the customer has any health conditions already present or not. Each health condition increases the total amount by a different %, and there can be more than one health condition present, in which case the total will be increased according to the order of the if statements. For example, the customer may have "Bone marrow", in which case the total is multiplied by 20%, or they may have "Bone marrow" and "Cancer" in which case the total is increased by 20% and then 25% in that order.
I have this written in multiple independent if statements because unlike with an if else statement, there can be more than one health condition present. Is there a way I can write this in a way that's more elegant than just a long list of if statements?
if (customer.getHealthConditions().equals("Bone Marrow")) {
total *= 1.2;
}
if (customer.getHealthConditions().equals("Cancer")) {
total *= 1.25;
}
if (customer.getHealthConditions().equals("Cardiovascular Disease")) {
total *= 1.3;
}
if (customer.getHealthConditions().equals("Gastrointestinal")) {
total *= 1.1;
}
if (customer.getHealthConditions().equals("Infections")) {
total *= 1.1;
}
if (customer.getHealthConditions().equals("Kidneys")) {
total *= 1.25;
}
if (customer.getHealthConditions().equals("Lungs")) {
total *= 1.25;
}
if (customer.getHealthConditions().equals("Musculoskeletal")) {
total *= 1.3;
}
Upvotes: 0
Views: 1152
Reputation: 153
I think here an enum could be useful, we need not only to sum all the values but also the order may be important (the progressive premium increase changes otherwise)
import java.util.Comparator;
import java.util.Optional;
import static java.util.Arrays.*;
enum HealthConditionPremium {
boneMarrow(1,1.2, "Bone Marrow"),
cancer(2,1.25, "Cancer"),
cardiovascularDisease(3,1.3, "Cardiovascular Disease"),
gastrointestinal(4,1.1, "Gastrointestinal"),
infections(5,1.1, "Infections"),
kidneys(6,1.25, "Kidneys"),
lungs(7,1.25, "Lungs"),
musculoskeletal(8,1.3, "Musculoskeletal");
public final int order;
public final double premiumIncrease;
public final String matchString;
HealthConditionPremium(int order, double premiumIncrease, String matchString) {
this.order = order;
this.premiumIncrease = premiumIncrease;
this.matchString = matchString;
}
static Optional<HealthConditionPremium> of(String condition) {
return stream(values()).filter(healthCondition -> healthCondition.matchString.equals(condition)).findAny();
}
public static double totalForHealthConditions(String ...conditions) {
return stream(conditions).
filter(condition -> condition != null && !condition.isEmpty()).
map(HealthConditionPremium::of).
filter(Optional::isPresent).
map(Optional::get).
sorted(Comparator.comparingInt(hc -> hc.order)).
map(healthConditionPremium -> healthConditionPremium.premiumIncrease).
reduce(1.0, (total, additionalPremium) -> total * additionalPremium);
}
}
class Scratch {
public static void main(String[] args) {
Customer customer = new Customer("Gastrointestinal");
double total = 1;
if (customer.getHealthConditions().equals("Bone Marrow")) {
total *= 1.2;
}
if (customer.getHealthConditions().equals("Cancer")) {
total *= 1.25;
}
if (customer.getHealthConditions().equals("Cardiovascular Disease")) {
total *= 1.3;
}
if (customer.getHealthConditions().equals("Gastrointestinal")) {
total *= 1.1;
}
if (customer.getHealthConditions().equals("Infections")) {
total *= 1.1;
}
if (customer.getHealthConditions().equals("Kidneys")) {
total *= 1.25;
}
if (customer.getHealthConditions().equals("Lungs")) {
total *= 1.25;
}
if (customer.getHealthConditions().equals("Musculoskeletal")) {
total *= 1.3;
}
System.out.println("total = " + total);
System.out.println("----------------------------------");
double totalWithEnum = HealthConditionPremium.totalForHealthConditions("Gastrointestinal");
System.out.println("totalWithEnum = " + totalWithEnum);
System.out.println("----------------------------------");
double totalManyWithEnum = HealthConditionPremium.totalForHealthConditions("Gastrointestinal", "Cancer", "Kidneys");
System.out.println("totalManyWithEnum = " + totalManyWithEnum);
double totalManyWithEnumDifferentOrder = HealthConditionPremium.totalForHealthConditions("Cancer", "Gastrointestinal", "Kidneys");
System.out.println("totalManyWithEnumDifferentOrder = " + totalManyWithEnumDifferentOrder);
}
static class Customer {
private final String condition;
Customer(String condition) {
this.condition = condition;
}
public String getHealthConditions() {
return condition;
}
}
}
Output
total = 1.1
----------------------------------
totalWithEnum = 1.1
----------------------------------
totalManyWithEnum = 1.71875
totalManyWithEnumDifferentOrder = 1.71875
Some words of advice :)
customer.getHealthConditions()
actually returns an array of Strings to pass to totalForHealthConditions
Upvotes: 1
Reputation: 19545
It seems that switch
statement is more appropriate in this case:
double quotient = 1.0;
switch(customer.getHealthConditions()) {
case "Bone Marrow":
quotient = 1.2; break;
case "Cancer":
case "Kidneys":
case "Lungs":
quotient = 1.25; break;
case "Cardiovascular Disease":
case "Musculoskeletal":
quotient = 1.3; break;
case "Gastrointestinal":
case "Infections":
quotient = 1.1; break;
}
total *= quotient;
In Java 12+ switch
statement was enhanced with multiple cases and arrow ->
so it may be written as:
total *= switch(customer.getHealthConditions()) {
case "Bone Marrow" -> 1.2;
case "Cancer", "Kidneys", "Lungs" -> 1.25;
case "Cardiovascular Disease", "Musculoskeletal" -> 1.3;
case "Gastrointestinal", "Infections" -> 1.1;
default -> 1.0;
}
Update
If health conditions are multiple, then equals
is not applicable at all, instead String::contains
or Collection::contains
should be used and it would be better to have a map or enum of the disease to quotient:
Map<String, Double> quotients = Map.of(
"Bone Marrow", 1.2,
"Cancer", 1.25,
"Kidneys", 1.25,
"Lungs", 1.25
// ...
);
total *= quotients.entrySet().stream()
.filter(e -> customer.getHealthConditions().contains(e.getKey()))
.map(Map.Entry::getValue)
.reduce(1.0, (p, v) -> p * v);
Upvotes: 5