首页 > 解决方案 > Java中的lambda函数树?

问题描述

我正在移植一些软件,它可以在 Swift 和 JavaScript 中运行,但我无法弄清楚如何在 Java 中进行。

JavaScript 版本如下所示:

var obj = { "A": {
      "1": (params) => { console.log("A1", params); },  
      "2": (params) => { console.log("A2", params); }
    }, // A
    "B": {
      "1": (params) => { console.log("B1", params); },  
      "2": (params) => { console.log("B2", params);}
     }, //B
}; // obj

在运行时,应用程序引擎调用

var a = 'A'; 
var i = '2';
obj[a][i](params);

我一生都无法弄清楚如何在 Java 中做到这一点。一个关键约束(没有双关语)是代码必须在结构上与其他端口相似。

以前,我试图使用 Object[][],

Map<String, Object> map = Stream.of(obj).collect(Collectors.toMap(data -> (String) data[0], data -> (Object) data[1]));

能够嵌入一些 Map<String, Integer> 对象。例子:

Map<String, Integer> colorMap = Stream.of(new Object[][] {
        {"black", 0x000000},
        {"navy", 0x000080},
};

我试图得出类似的代码,但 Java 不喜欢它,因为 lambdas 和 Object 不兼容。

我希望得到的代码是:

Map<String, Map<String, Callable<Void> > > obj =  Stream.of(new Object[][] {
  {"A", Stream.of(new Object[][] {
    {"1", (params)->{ System.out.println("A1"); } },
    {"2", (params)->{ System.out.println("A2"); } } }),
  {"B", Stream.of(new Object[][] {
    {"1", (params)->{ System.out.println("B1"); } },
    {"2", (params)->{ System.out.println("B2"); } } } )}
  } 
});
...
// call the function (assuming A and 1 exist)
obj.get("A").get("1")(params);

但我对如何将其转换为能够使用 lambdas 感到困惑。我不断收到的错误是: error: incompatible types: Object is not a functional interfaceerror: lambda expression not expected here

标签: javalambda

解决方案


一种可能的 Java 结构保留翻译是:

Map<String, Map<String, Runnable>> obj = Map.of(
    "A", Map.of(
        "1", () -> System.out.println("A1"),
        "2", () -> System.out.println("A2")
    ),
    "B", Map.of(
        "1", () -> System.out.println("B1"),
        "2", () -> System.out.println("B2")
    )
);

你像这样使用它:

obj.get("A").get("2").run();

如果您需要传递参数或从函数返回值,请替换Runnable为不同的函数接口。您可能必须定义自己的一个。例如:

@FunctionalInterface
interface FunctionWithObjectParameters {
    void run(Object... args);
}

更新:如果您需要在 Java 8 中执行此操作,一种选择是使用具有以更方便的方式构建地图的方法的外部库 - 例如guava collect

另一种选择是自己实现便利方法。Map.of不做任何魔术,您可以轻松地将其替换为您自己的“mapOf”方法:

static <K, V> Map<K, V> mapOf(K key1, V value1) {
    return mapOfEntries(entry(key1, value1));
}

static <K, V> Map<K, V> mapOf(K key1, V value1, K key2, V value2) {
    return mapOfEntries(entry(key1, value1), entry(key2, value2));
}

static <K, V> Map<K, V> mapOf(K key1, V value1, K key2, V value2, K key3, V value3) {
    return mapOfEntries(entry(key1, value1), entry(key2, value2), entry(key3, value3));
}

// Add  more overloads if you need

static <K, V> Map<K, V> mapOfEntries(Map.Entry<K, V>... args) {
    // On Android, you may want to use ArrayMap instead of HashMap
    Map<K, V> map = new HashMap<>();
    for (Map.Entry<K, V> arg : args) {
        map.put(arg.getKey(), arg.getValue());
    }
    return map;
}

static <K, V> Map.Entry<K, V> entry(K key, V value) {
    return new AbstractMap.SimpleEntry<>(key, value);
}

推荐阅读