Существует ли способ иметь параметр, который может запускать все предыдущие обращения в инструкции switch?

#java #switch-statement #case #option

Вопрос:

Например, если пользователь выбирает вариант 1 — 3, он выполняет свою собственную конкретную задачу. Если пользователь вводит 4, он выполняет все варианты 1 — 3. Есть ли способ выполнить это с помощью инструкции switch без необходимости копировать и вставлять весь код из каждого из случаев?

 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;
    }
}
 

Комментарии:

1. Перерыв условно. Сверху положите 4.

2. Хотя предложение @BoristheSpider сработало бы, я думаю, что оно уродливо и запутанно. Просто сделайте один вызов метода в каждом из случаев 1, 2 и 3 и повторите три вызова в случае 4.

3. Вы можете найти en.m.wikipedia.org/wiki/Duff’s_device интересно.

4. Привет @M. Руиз, у вас могут быть только эти четыре условия, мы можем использовать continue вместе с управлением флагами для решения проблемы. в соответствии с вашим вышеуказанным кодом. Если у вас есть какая-либо динамическая логика, нам нужно позаботиться об этом.

5. Зачем вам это нужно только для некоторых заявлений о печати? Если вы говорите о более сложном коде, переместите код в методы , а затем вызовите методы. Методы позволяют повторно использовать код.

Ответ №1:

switch оператор не допускает повторения case , поэтому запрашиваемая функциональность может быть достигнута только при if использовании нескольких операторов ИЛИ операции:

 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");
}
 

Другой подход может заключаться в подготовке карты вариантов определенных действий или списков действий для реализации требуемой логики.

  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);
    }
}
 

Тест:

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

Выход:

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

Этот метод облегчает любую композицию действий, а не только наличие одного действия для выполнения всех доступных действий.

 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);
}