簡體   English   中英

在 Java 中的哈希圖中將參數傳遞給 lambda 的最佳方法

[英]Best way to pass arguments to a lambda in a hashmap in Java

我有一個接受不同命令的 CLI。 為了避免一個可擴展的長 switch 語句,我決定將我的命令放在一個哈希圖中,並有一個函數來檢查命令是否存在,如果存在則調用它。

public class Commands {
  private LinkedHashMap<String, Runnable> commands = new LinkedHashMap<String, Runnable>();

  public Commands(Scanner userInput) {
    commands.put("foo", () -> this.foo());
    commands.put("bar", () -> this.bar());
    commands.put("foobar", () -> this.foobar());
    ... and so on 
  }

  private void handleCommand(String command) {
    if (!commands.containsKey(command)) {
      System.out.printf("'%s' is an invalid command%n", command);
      return;
    }

    commands.get(command).run();
  }

  public void foo() { ... }
  public void bar() { ... }
  public void foobar() { ... }
}

這創造了奇跡,我已經能夠快速添加大量命令。

我現在有一個問題,我的一些命令需要參數。 例如$ foo arg1 arg2並且我想保留我最初以這種方式編寫的結構,因為我認為它很容易擴展。

我已經改變了我的 handleCommand() 方法,如下所示:

  private void handleCommand(String command) {
    // Split the command to get possible args
    String[] args = command.split(" ");

    if (!commands.containsKey(args[0])) { // the first string is the command we want
      System.out.printf("'%s' is an invalid command%n", args[0]);
      return;
    }

    commands.get(args[0]).run(Arrays.copyOfRange(args, 1, args.length));
  }

並像這樣修改適當的方法

    ...
    commands.put("foo", (args) -> this.foo(args));
    ...

    public void foo(String[] args) { ... };

我也嘗試過使用我覆蓋run的接口,我嘗試過使用 Callable 而不是 Runnable。 我現在不知道該嘗試什么。 我發現的很多例子比我需要的要復雜得多,我很難遵循它們。

我來自一個 javascript 背景,在那里完全可以做到:

obj = { foo: (args) => { ...do something with args } }

obj.foo(args)

所以這就是我為什么要這樣做的原因。

TIA

您可以使用Consumer而不是Runnable Consumer接受一個參數並且不返回任何內容。 如果您還想返回一個參數,您需要使用Function 所以你的代碼看起來像這樣:

private LinkedHashMap<String, Consumer<String[]>> commands = new LinkedHashMap<>();

public Commands(Scanner userInput) {
    commands.put("foo", this::foo); // with method reference. Its the same as next line
    commands.put("bar", input -> this.bar(input));
    commands.put("foobar", input -> this.foobar(input));
}

....
commands.get(command).accept(args); // Consumer's methods is accept

您可以在此處查看預定義的功能接口。

除了使用Consumer<String[]> ,您還可以為要實現的命令定義自定義接口:

public static interface Command {
    public void run(String ... args);
}

要完全按照您的預期使用:

private LinkedHashMap<String, Command> commands = new LinkedHashMap<>();

commands.put("foo", (input) -> foo(input));

不要害怕聲明自己的特定接口。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM