Java 8 Map<String, Runnable> Control Flow

1.9k Views Asked by At

I'm trying to familiarize myself with some new Java 8 functionality (ha) but I'm having some control flow mishaps.

In the following code, I have a Map<String, Runnable> so I can call methods based on their name, but I can't seem to figure out how to do two things:

  1. How can I make these methods take parameters? I.e. what is the syntax I need in the map "put"s.
  2. When I call these methods from the "get" method in "Dispatch, I cannot return the return value of the method (Status). I suspect this has something to do with where the method is being called, but I can't figure it out. Status is just an enum and the toList method just takes a space separated string and returns a list (this is meant to be used as a REPL).

import java.util.*;

public class Dispatcher {
    private Map<String, Runnable> func;
    private Status status;
    private List<String> command;
    Optional<List<String>> opt;

    public Dispatcher() {
        func = new HashMap<>();
        func.put("Method1", this::Method1);
        func.put("Method2", this::Method2);
        func.put("Help", this::Help);
        status = Status.DONE;
    }

    private Status Help() {
        return Status.DONE;
    }

    private Status Method1() {
        return Status.DONE;
    }

    private Status Method2() {
        return Status.DONE;
    }

    /**
     * Execute the given command on a new process.
     * @param command the full command requested by the caller including command name and arguments.
     * @return The status of the requested operation.
     */
    public Status Dispatch(String command) {
        opt = CommandInterpreter.toList(command);
        opt.orElse(new LinkedList<String>(){{add("Help");}});
        func.get(opt.get().get(0));
        return Status.DONE;
    }
}
3

There are 3 best solutions below

0
Harmlezz On BEST ANSWER

Here is a skeleton how you may start do deal with commands taking zero or more arguments and returning a status code. It is just a blueprint, an example. Perhaps it helps you getting started:

public class Dispatcher {

    public static final int SUCCESS = 0;

    public static final int FAILURE = 1;

    public static final Command HELP = (args) -> {
        String command = args[0];
        System.out.println("Usage of " + command + ": bla bla");
        return FAILURE;
    };

    public static final Command RENAME = (args) -> {
        File oldName = new File(args[1]);
        File newName = new File(args[2]);
        return oldName.renameTo(newName) ? SUCCESS : FAILURE;
    };

    public final Map<String, Command> commands = new HashMap<String, Command>() {{
        put("help", HELP);
        put("rename", RENAME);
    }};

    public int dispatch(String commandLine) {
        String[] args = commandLine.split("\\s");
        return Optional.ofNullable(commands.get(args[0]))
                .orElse(HELP)
                .execute(args);
    }
}

interface Command {
    int execute(String... args);
}
0
Louis Wasserman On

If you want the methods to take arguments, then you don't want to store it as Runnable. You might want Consumer, or another custom functional interface that accepts an argument -- if you want a return value, use Function, or create your own interface.

0
shmosel On

The Runnable interface doesn't accept any parameters or have a return type. To add a return type, you can use Supplier<Status>. To add a parameter, use Function<ParamType, Status>.