Search code examples
javadictionaryswitch-statementjava-streamlanguage-agnostic

Using Map/Dictionary as an alternative to switch case


At the risk of this being an opinion based question, would creating a Map/dictionary where the keys are predicates and the values the action to be made be a good and viable substitute for switch case?

For example (following Java Map) :

    Map.of(predicate1, action1, ... predicateN, actionN)
    .entrySet().stream()
    .filter(e -> e.getKey()).findAny()
    .ifPresentOrElseThrow().getValue();

Solution

  • It's an interesting approach, I sometimes do it for filters or mappers. The only thing I would change would be to avoid using a Map if you don't really need one (what would be the hashcode of your Predicate - it can be looked up, but still, it's not super straightforward).

    Instead, you can put the Predicate and the Consumer in some sort of Pair<> or Tuple<>, or even create your own structure:

    record PossibleAction<T>(
            Predicate<T> predicate,
            Consumer<T> action
    ) {
        // if you use a custom structure you can define these methods
        // and use .appliesFor(data) instead of using .getPredicate().test(data)
        public boolean appliesFor(T data) {
            return predicate.test(data);
        }
    
        public void apply(T data) {
            action.accept(data);
        }
    }
    

    Now you can have a list of these PossibleActions:

    List<PossibleAction<String>> actions = List.of(
        new PossibleAction<>(s -> s.contains("A"), s -> System.out.println("1") ),
        new PossibleAction<>(s -> s.contains("B"), s -> System.out.println("2") ),
        new PossibleAction<>(s -> s.contains("C"), s -> System.out.println("3") )
    );
    

    And you can use this, as pointed out by you in the initial post:

    void performActions(String data) {
        actions.stream()
                .filter(a -> a.appliesFor(data))
                .forEach(a -> a.apply(data));
    }