3

I have Strings where I need to find brackets (), {}, [] and using stack to check correctness and if there is a mistake to print the position of mistake . So i split them into char array and then want to check symbol by symbol and if its match my map execute my method of pushing/popping to/from the stack.

I imagine it like this:

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 

So is there something like this? Or I have to use switches?

Neuron
  • 5,141
  • 5
  • 38
  • 59
Eugene Shymko
  • 173
  • 2
  • 11
  • Check this blog post for checking correctness.. expand it to print position of mistake.. http://c-madeeasy.blogspot.com/2011/08/java-program-to-check-whether.html – Sachin Feb 14 '16 at 23:47
  • Your "example" isn't even putting methods into the map. You are putting the return values of push and pop – OneCricketeer Feb 14 '16 at 23:48

3 Answers3

1

Since java is not a functional programming language (where functions are so-called first-class citizens), you can't pass a function by reference. What you could do instead is create an interface with one method called for example execute(). you then implement this interface for each function you want to have and put these in the map, where you can call them easily and execute these "functions".

public interface function{
    void execute();
}

And (in java 8) your code could look something like this:

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

Some people would even write it like that:

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

Which I don't think is as easy to read, but that's a matter of preference.

To execute your Function use:

map.get('(').execute();
Neuron
  • 5,141
  • 5
  • 38
  • 59
0

You are calling the method instead of putting it into the map. What you could do instead is to put an instance of the Runnable interface into the map. Runnable is Javas default interface for any method that has no parameter list and no return value. If you need parameters or a return value, you might want to have a look at the interfaces in the package java.util.function. For example Supplier<T> has a return value and Consumer<T> has one parameter.

Here is an example using Java 8 lambda expressions:

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

And the usage:

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

The run() method is declared by the Runnable interface and will call the method that you put into the map. Don't be confused by the different names.

Stefan Dollase
  • 4,530
  • 3
  • 27
  • 51
0

Use BooleanSupplier instead of Method.

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

And check like this.

    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 ')'

Or you can use 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);