使用 Map/Dictionary 作为切换大小写的替代方法

Using Map/Dictionary as an alternative to switch case

提问人:Shmuel Greenberger 提问时间:4/19/2023 最后编辑:Shmuel Greenberger 更新时间:5/10/2023 访问量:98

问:

冒着这是一个基于意见的问题的风险,创建一个键是谓词和值的映射/字典是要执行的操作是否是开关大小写的良好且可行的替代品?

例如(以下 Java Map):

    Map.of(predicate1, action1, ... predicateN, actionN)
    .entrySet().stream()
    .filter(e -> e.getKey()).findAny()
    .ifPresentOrElseThrow().getValue();
java 字典 switch-statement java-stream 语言不可知

评论


答:

1赞 Emanuel Trandafir 4/19/2023 #1

这是一种有趣的方法,我有时会为过滤器或映射器这样做。我唯一要改变的是,如果你真的不需要一个,就避免使用一个(你的谓词的哈希码是什么 - 它可以查找,但仍然不是超级简单)。Map

相反,你可以将谓词和消费者放在某种 or 中,甚至可以创建你自己的结构:Pair<>Tuple<>

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

现在你可以有一个列表: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") )
);

正如您在最初的帖子中指出的那样,您可以使用它:

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

评论

0赞 Shmuel Greenberger 4/20/2023
谢谢。你能解释一下谓词的哈希码有什么问题吗?
0赞 Shmuel Greenberger 4/20/2023
我还要指出,您在最后描述的函数中的方法是可变的,这不是过滤时预期的操作。
0赞 Emanuel Trandafir 4/20/2023
当然,这只是一个示例,您可以使用 Function 而不是 Consumer
0赞 Shmuel Greenberger 5/3/2023
你仍然没有解释你所说的谓词哈希码问题是什么意思!
0赞 Emanuel Trandafir 5/3/2023
我没有说有问题,但要知道它们是如何计算的可能很困难/很棘手。对于对象,可以根据其字段进行计算,但对于函数,确定它可能更难。此外,每当有一个 but 我们只使用它时,这可能表明它可以有更合适的数据结构。MapentrySet()