如何将方法放在地图中?

How to put method in map?

我有字符串,我需要在其中找到方括号 (){}[] 并使用堆栈检查正确性,如果有错误则打印错误的位置。所以我将它们拆分为 char 数组,然后想逐个检查符号,如果它与我的映射匹配,则执行我的 pushing/popping to/from 堆栈方法。

我是这样想象的:

ParentStack s = new ParentStack();
Map<Character, Method> map = new HashMap<Character, Method>();
map.put('(', s.push('('));
map.put(')', s.pop()); //then check if its opposite 

所以有这样的东西吗?或者我必须使用开关?

由于 java 不是函数式编程语言(这里的函数就是所谓的 first-class citizens),您不能通过引用传递函数。您可以做的是创建一个接口,其中包含一个名为 execute() 的方法。然后你为每个你想拥有的功能实现这个接口并将它们放在映射中,在那里你可以轻松地调用它们并执行这些 "functions".

public interface function{
    void execute();
}

并且(在 java 8 中)您的代码可能如下所示:

ParentStack s = new ParentStack();
Map<Character, Method> map = new HashMap<Character, Method>();
map.put('(', (Function) () -> s.push('('));
map.put(')', (Function) () -> s.pop());

有些人甚至会这样写:

map.put('(', () -> s.push('('));

我认为这不太容易阅读,但这是一个偏好问题。

要执行您的 Function 使用:

map.get('(').execute();

您正在调用该方法,而不是将其放入地图中。您可以做的是将 Runnable 接口的实例放入地图中。 Runnable 是 Java 任何没有参数列表和 return 值的方法的默认接口。如果您需要参数或 return 值,您可能需要查看包 java.util.function 中的接口。例如 Supplier<T> 有一个 return 值,而 Consumer<T> 有一个参数。

这是一个使用 Java 8 个 lambda 表达式的示例:

ParentStack s = new ParentStack();
Map<Character, Runnable> map = new HashMap<Character, Runnable>();
map.put('(', () -> s.push('('));
map.put(')', () -> s.pop());

以及用法:

map.get('(').run();

run()方法由Runnable接口声明,将调用您放入地图的方法。不要被不同的名字搞糊涂了。

使用 BooleanSupplier 代替 Method

    Stack<Character> s = new Stack<>();
    Map<Character, BooleanSupplier> map = new HashMap<>();
    map.put('(', () -> { s.push('('); return true; });
    map.put(')', () -> !s.isEmpty() && s.pop() == '(');

然后像这样检查。

    String str = "((ab)c)";
    int errorAt = -1;
    for (int i = 0; i < str.length(); ++i) {
        char c = str.charAt(i);
        if (map.containsKey(c))
            if (!map.get(c).getAsBoolean()) {
                errorAt = i;
                break;
            }
    }
    if (errorAt == -1 && s.isEmpty())
        System.out.println("OK!");
    else if (errorAt == -1)
        System.out.println("error at " + str.length());  // too few ')'
    else
        System.out.println("error at " + errorAt);  // too many ')'

或者您可以使用 Stream API。

    int errorAt = IntStream.range(0, str.length())
        .filter(i -> map.containsKey(str.charAt(i)))
        .reduce(-1, (p, i) -> p >= 0 || map.get(str.charAt(i)).getAsBoolean() ? p : i);