Using Java I am attempting to create the Cartesian Product of a map which contains String
keys and List<String>
values. I need to preserve the values of the keys when creating the list like so:
- From a
Map<String, List<String>>
Object - To a
List<Map<String, String>>
Object
I also have the requirement that when a List<String>
value in the original map is empty it should still be treated as a single value when creating the Cartesian Product so as to avoid multiplying by 0 and creating no maps. For example the following map:
{
"Location Number" = {"100", "500"}
"Department Number" = {"11", "22", "33"}
"District Number" = {}
"Preferred Language" = {"en-US"}
}
Is translated to:
{
{
"Location Number" = "100"
"Department Number" = "11"
"District Number" = {}
"Preferred Language" = "en-US"
},
{
"Location Number" = "100"
"Department Number" = "22"
"District Number" = {}
"Preferred Language" = "en-US"
},
{
"Location Number" = "100"
"Department Number" = "33"
"District Number" = {}
"Preferred Language" = "en-US"
},
{
"Location Number" = "500"
"Department Number" = "11"
"District Number" = {}
"Preferred Language" = "en-US"
},
{
"Location Number" = "500"
"Department Number" = "22"
"District Number" = {}
"Preferred Language" = "en-US"
},
{
"Location Number" = "500"
"Department Number" = "33"
"District Number" = {}
"Preferred Language" = "en-US"
}
}
Below is the code I am currently using to accomplish a similar translation, but it does not retain the key, which I need. I do not know if this is possible to accomplish using Java 8 Streams in general.
private static List<List<String>> createRuleListFromMap(Map<String, List<String>> ruleMap) {
List<List<String>> ruleList = new ArrayList<>();
cartesianProduct(ruleMap.values()).forEach(ruleList::add);
return ruleList;
}
private static <T> Stream<List<T>> cartesianProduct(Collection<? extends Collection<T>> collections) {
return cartesianProduct(new ArrayList<Collection<T>>(collections), Collections.emptyList());
}
private static <T> Stream<List<T>> cartesianProduct(List<? extends Collection<T>> collections, List<T> current) {
return collections.isEmpty() ? Stream.of(current) : collections.get(0).stream().flatMap(e -> {
List<T> list = new ArrayList<>(current);
list.add(e);
return cartesianProduct(collections.subList(1, collections.size()), list);
});
}