Search code examples
javaswitch-statementcase

Is there a way to have an option that can run all previous cases in a switch statement?


For example, if the user selects option 1 - 3 it does their own specific task. If user enters 4, it does all options 1 - 3. Is there a way to accomplish this using switch statement without having to copy and paste all code from each of the cases?

switch (option) {
    case 1: {
        System.out.println("1");
        break;
    }
    case 2: {
        System.out.println("2");
        break;
    }
    case 3: {
        System.out.println("3");
        break;
    }
    case 4: {
        System.out.println("1");
        System.out.println("2");
        System.out.println("3");
        break;
    }
    default: {
        System.out.print("Invalid selection.");
        break;
    }
}

Solution

  • switch statement does not allow repeated case's, so requested functionality may be achieved only with multiple if statements using OR operation:

    if (option == 1 || option == 4) {
        System.out.println("1");
    }
    if (option == 2 || option == 4) {
        System.out.println("2");
    }
    if (option == 3 || option == 4) {
        System.out.println("3");
    }
    

    Another approach could consist in preparing a map of options to certain actions or lists of actions to implement required logic.

    1. Map<Integer, Runnable> + Predicate.or
    // define a map of simple actions
    static final Map<Integer, Runnable> actionMap = new LinkedHashMap<>(); 
    static {
        actionMap.put(1, ()-> System.out.println("1"));
        actionMap.put(2, ()-> System.out.println("2"));
        actionMap.put(3, ()-> System.out.println("3"));
    };
    
    public static void runOption(Integer option) {
        if (option < 1 || option > 4) {
            System.out.println("No action found for option = " + option);
        } else {
            Predicate<Integer> is4 = (x) -> 4 == option;
            
            actionMap.keySet()
                .stream()
                .filter(is4.or(option::equals))
                .map(actionMap::get)
                .forEach(Runnable::run);
        }
    }
    

    Test:

    IntStream.range(0, 6).boxed().forEach(MyClass::runOption);
    

    Output:

    No action found for option = 0
    1
    2
    3
    1
    2
    3
    No action found for option = 5
    
    1. Map<Integer, List<Runnable>> with getOrDefault

    This method facilitates any composition of actions, not only having one action to run all available actions.

    static Runnable 
        action1 = ()-> System.out.println("1"),
        action2 = ()-> System.out.println("2"),
        action3 = ()-> System.out.println("3");
    
    static final Map<Integer, List<Runnable>> actionListMap = Map.of(
        1, Arrays.asList(action1),
        2, Arrays.asList(action2),
        3, Arrays.asList(action3),
        4, Arrays.asList(action1, action2, action3)
    );
    
    public static void runOptionList(Integer option) {
        actionListMap.getOrDefault(
            option, 
            Arrays.asList(() -> System.out.println("No action found for option = " + option))
        )
        .forEach(Runnable::run);
    }