From a java.util.function.BiFunction
that maps a pair of Enum
s into a value, I want to build a EnumMap
that reflects that mapping.
For instance, let E1
and E2
be enum
types and T
any given type:
BiFunction<E1,E2, T> theBiFunction = //...anything
EnumMap<E1,EnumMap<E2,T>> theMap =
buildTheMap( // <-- this is where the magic happens
E1.values(),
E2.values(),
theBiFunction);
Given any pair of values of type E1
and E2
E1 e1 = //any valid value...
E2 e2 = //any valid value....
both values below should be equal:
T valueFromTheMaps = theMap.get(e1).get(e2);
T valueFromTheFunction = theBiFunction.apply(e1,e2);
boolean alwaysTrue = valueFromTheMaps.equals(valueFromTheFunction);
What's the best (more elegant, efficient, etc...) implementation for the method where the "magic" takes place?
You get an elegant solution if you go to a generic solution and break it down. First, implement a generic function which creates an EnumMap
out of a Function
, then implement the nested mapping of a BiFunction
using the first function combined with itself:
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);
}
Here’s a little test case:
enum Fruit {
APPLE, PEAR
}
enum Color {
RED, GREED, YELLOW
}
…
EnumMap<Fruit, EnumMap<Color, String>> result
=biFuncToMap((a,b)->b+" "+a,
Fruit.class, Color.class, Fruit.values(), Color.values());
System.out.println(result);
→
{APPLE={RED=RED APPLE, GREED=GREED APPLE, YELLOW=YELLOW APPLE}, PEAR={RED=RED PEAR, GREED=GREED PEAR, YELLOW=YELLOW PEAR}}
Of course, using the generic solution you can built methods for concrete enum
types which do not require the Class
parameter(s)…
This ought to work smoothly with a parallel stream if the provided (Bi)Function
is thread safe.