如何在地图中放置方法?

时间:2016-02-14 23:33:38

标签: java dictionary functional-programming first-class-functions

我有字符串,我需要找到括号(){}[]并使用堆栈检查正确性以及是否有错误来打印错误的位置。所以我将它们分成char数组,然后想要逐个符号检查,如果它匹配我的地图执行我的方法推送/弹出堆栈。

我想像这样:

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 

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

3 个答案:

答案 0 :(得分:1)

由于java不是函数式编程语言(函数是所谓的first-class citizens),因此您无法通过引用传递函数。您可以做的是使用一个名为execute()的方法创建一个接口。然后,您可以为要使用的每个函数实现此接口,并将它们放在地图中,您可以在其中轻松调用它们并执行这些&#34;函数&#34;。

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

答案 1 :(得分:0)

您正在调用方法而不是将其放入地图中。你可以做的是将Runnable接口的实例放入地图中。 Runnable是任何没有参数列表且没有返回值的方法的Javas默认接口。如果需要参数或返回值,可能需要查看包java.util.function中的接口。例如,Supplier<T>有一个返回值,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接口声明,并将调用您放入地图的方法。不要被不同的名字搞糊涂。

答案 2 :(得分:0)

使用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);