【问题标题】:Mapping functions to elements of array将函数映射到数组元素
【发布时间】:2020-12-24 02:34:25
【问题描述】:

我有一个关于在 java 中映射事物的一般性问题。我并没有完全陷入困境,但我觉得我的方法并不是很漂亮,如果想象我的小型私人项目会变得更大,可能会导致问题。

想象一下,我有一个数组 = {1, 2, 3, 4},它不一定是数字,只是一般的任何符号。 然后我从用户那里得到一个输入,它只能是数组的一部分(不可能有无效的输入)。现在取决于他们选择的元素,将执行特定的功能。我唯一想到的是:

switch (input) {
   case array[0]:
      doOneThing();
      break;
   case array[1]:
      doAnotherThing();
     break;
   case array[2]:
      doAThirdThing();
      break;
   case array[3]:
      doSomethingElse();
       break;
}

这种方法有效,但扩展起来并不美观。我非常感谢所有可能的想法。

【问题讨论】:

  • 您是否尝试编译该结构?案例目标必须是常量,并且数组元素不符合该要求。
  • 是的,我收到了那个错误。所以我的方法甚至不起作用。你知道如何制作一个常量数组吗?

标签: java arrays function mapping


【解决方案1】:

您的 switch 语句中必须有常量,这样您指定的内容将不起作用。作为一个例子,你可以做这样的事情。您不仅限于使用 Runnable lambdas。可以使用任何功能接口,并在调用时提供适当的参数。

请注意,允许调用 any 类的 any 方法不是一个好主意,因为它可能会导致意外结果或安全问题,具体取决于它的使用方式。

public class ThisClass {
    
    public static void main(String[] args) {
        Map<String, Runnable> map = new HashMap<>();
        ThisClass tc = new ThisClass();
        
        map.put("A", () -> tc.doOneThing());
        map.put("B", () -> tc.doAnotherThing());
        map.put("C", () -> tc.doAthirdThing());
        map.put("D", () -> tc.doSomethingElse());
        
        for (String str : new String[] { "A", "B", "Q", "C", "D", "E" }) {
            map.getOrDefault(str, () -> tc.defaultMethod()).run();
        }
    }
    
    public void doOneThing() {
        System.out.println("Doing one thing");
    }
    
    public void defaultMethod() {
        System.out.println("Executing default");
    }
    
    public void doAnotherThing() {
        System.out.println("Doing Another thing");
    }
    
    public void doAthirdThing() {
        System.out.println("Doing a third thing");
    }
    
    public void doSomethingElse() {
        System.out.println("Doing something Else");
    }
}

打印

Doing one thing
Doing Another thing
Executing default
Doing a third thing
Doing something Else
Executing default

你也可以这样做。

Map<String, DoubleBinaryOperator> map = new HashMap<>();

map.put("+", (a, b) -> a + b);
map.put("-", (a, b) -> a - b);
map.put("*", (a, b) -> a * b);
map.put("/", (a, b) -> a / b);

DoubleBinaryOperator error = (a, b) -> {
    throw new IllegalArgumentException();
};

for (String str : new String[] { "+", "-", "L", "/", "*" }) {
    try {
        double result = map.getOrDefault(str, error)
                .applyAsDouble(2.0, 3.0);
        System.out.println("result = " + result);
    } catch (IllegalArgumentException iae) {
        System.out.println("unknown operator \"" + str + "\"");
    }
}

打印

result = 5.0
result = -1.0
unknown operator "L"
result = 0.6666666666666666
result = 6.0

【讨论】:

  • BruchGUI.java:12:18: 错误: 预期 map.put("+", () -> obj1.foo(obj2)); ^ obj1 和 obj2 是另一个类的对象
【解决方案2】:

一种可能的方法是,如果您可以使用输入的值创建函数的名称。例如,如果他们输入 1,您将调用“function1”,或者如果您输入 2,则调用“function2”。然后你可以使用反射通过它的字符串名称调用方法。

类似this.

【讨论】:

    【解决方案3】:

    听起来你想看看 Java Reflection Api。

    Class c=Class.forName("xxxx")
    

    其中 {xxxx} 是您从参数构造的字符串。

    您可以类似地调用方法名称。

    注意 - 漂亮的代码通常是有代价的 - 无论是可读性、性能还是安全性(尤其是反射的情况下)。就我个人而言,我不介意冗长的 switch 语句 - 它可能不漂亮,但它永远不会咬你。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-04
      • 2017-07-03
      • 2022-10-06
      • 1970-01-01
      • 2015-11-13
      • 2013-06-11
      • 1970-01-01
      相关资源
      最近更新 更多