简体   繁体   中英

How to convert if-else to Java8 Optional

How to change the below code to remove if-else and use Java8 Optional instead

public class IfTest {

    public static void main(String[] args) {
        String foodItem = "Apple";
        
        if(foodItem.equals("Apple") || foodItem.equals("A"))
            foodItem = "Fruit";
        else if(foodItem.equals("Potato") || foodItem.equals("P"))
            foodItem = "Vegetable";
        else 
            foodItem = "Food";
        
        System.out.println(foodItem);
    }
}

Optional isn't a general-purpose replacement for if/else. It is not a good choice here.

I think you could contrive to use Optional something like this:

Optional.of(foodItem)
    .map(f -> f.equals("Apple") || f.equals("A") ? "Fruit" : f)
    .map(f -> !f.equals("Fruit") && (f.equals("Potato") || f.equals("P")) ? "Vegetable" : f)
    .filter(f -> !f.equals("Fruit") && !f.equals("Vegetable"))
    .orElse("Food");

which is just a total unreadable mess.

An alternative would be switch : this is better because it doesn't search through all the cases linearly, but rather jumps to the matching one:

switch (foodItem) {
  case "Apple": case "A":
    foodItem = "Fruit"; break;
  case "Potato": case "P":
    foodItem = "Vegetable"; break;
  default:
    foodItem = "Food";
}

Or a switch expression (in Java 12+):

foodItem = switch (foodItem) {
  "Apple", "A" -> "Fruit";
  "Potato", "P" -> "Vegetable";
  default -> "Food";
}

If you want to use a feature added in Java 8, you can create a Map:

Map<String, String> map = new HashMap<>();
map.put("Apple", "Fruit");
map.put("A", "Fruit");
map.put("Potato", "Vegetable");
map.put("P", "Vegetable");

And then use map.getOrDefault(foodItem, "Food") . That's basically just a dynamic form of the switch.

Optional is not a good replacement for a chain of if - else if - else statements. You might want to perform a look-up in a hash-based data structure such as HashSet inside a class for the given food group:

@Getter
@AllArgsConstructor         // basically getters and all-args constructor
public class FoodGroup {
    String name;
    Set<String> items;
}
List<FoodGroup> list = List.of(                            // I use Java-9+ static method
    new FoodGroup("Fruit", Set.of("Apple", "A")),          // for Java 8, use Arrays.asList(..)
    new FoodGroup("Vegetable", Set.of("Potato", "P")));


String foodItem = "Apple";

String result = list.stream()
                    .filter(group -> group.getItems().contains(foodItem))
                    .map(FoodGroup::getName)
                    .findFirst()
                    .orElse("Food");

This solution might be an overkill for such a simple use-case, however, this solution is scalable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM