如何在Java的Lambda API中构建复制函数的Map

bru*_*uno 3 java lambda enum-map java-8 java-stream

从一个s java.util.function.BiFunction映射Enum到一个值,我想构建一个EnumMap反映该映射.

例如,let E1E2be是enum类型和T任何给定类型:

 BiFunction<E1,E2, T> theBiFunction = //...anything

 EnumMap<E1,EnumMap<E2,T>> theMap = 
    buildTheMap(                     // <--  this is where the magic happens
                E1.values(), 
                E2.values(),
                theBiFunction);
Run Code Online (Sandbox Code Playgroud)

给出任何类型E1和值的对E2

E1 e1 = //any valid value...
E2 e2 = //any valid value....
Run Code Online (Sandbox Code Playgroud)

以下两个值应相等:

T valueFromTheMaps = theMap.get(e1).get(e2);
T valueFromTheFunction = theBiFunction.apply(e1,e2);

boolean alwaysTrue = valueFromTheMaps.equals(valueFromTheFunction);
Run Code Online (Sandbox Code Playgroud)

" 神奇 "发生的方法的最佳(更优雅,更高效等)实现是什么?

Hol*_*ger 5

如果您使用通用解决方案并将其分解,您将获得一个优雅的解决方案.首先,实现一个通用函数,它创建一个EnumMapout Function,然后BiFunction使用与自身结合的第一个函数实现一个嵌套映射:

static <T,E extends Enum<E>>
  EnumMap<E,T> funcToMap(Function<E,T> f, Class<E> t, E... values) {
    return Stream.of(values)
      .collect(Collectors.toMap(Function.identity(), f, (x,y)->x, ()-> new EnumMap<>(t)));
}
static <T,E1 extends Enum<E1>,E2 extends Enum<E2>>
  EnumMap<E1,EnumMap<E2,T>> biFuncToMap(
  BiFunction<E1,E2,T> f, Class<E1> t1, Class<E2> t2, E1[] values1, E2[] values2){

  return funcToMap(e1->funcToMap(e2->f.apply(e1, e2), t2, values2), t1, values1);
}
Run Code Online (Sandbox Code Playgroud)

这是一个小测试案例:

enum Fruit {
    APPLE, PEAR
}
enum Color {
    RED, GREED, YELLOW
}
Run Code Online (Sandbox Code Playgroud)

...

EnumMap<Fruit, EnumMap<Color, String>> result
  =biFuncToMap((a,b)->b+" "+a,
     Fruit.class, Color.class, Fruit.values(), Color.values());
System.out.println(result);
Run Code Online (Sandbox Code Playgroud)

{APPLE={RED=RED APPLE, GREED=GREED APPLE, YELLOW=YELLOW APPLE}, PEAR={RED=RED PEAR, GREED=GREED PEAR, YELLOW=YELLOW PEAR}}
Run Code Online (Sandbox Code Playgroud)

当然,使用通用解决方案,您可以为enum不需要Class参数的具体类型构建方法......


如果提供的(Bi)Function是线程安全的话,这应该与并行流顺利工作.