Generating combinations with Java 8 Stream map
and reduce
methods.
Try it online!
public static <T> List<List<T>> combinations(List<List<T>> lists) {
// incorrect incoming data
if (lists == null) return Collections.emptyList();
return lists.stream()
// non-null and non-empty lists
.filter(list -> list != null && list.size() > 0)
// represent each list element as a singleton list
.map(list -> list.stream().map(Collections::singletonList)
// Stream<List<List<T>>>
.collect(Collectors.toList()))
// summation of pairs of inner lists
.reduce((list1, list2) -> list1.stream()
// combinations of inner lists
.flatMap(inner1 -> list2.stream()
// merge two inner lists into one
.map(inner2 -> Stream.of(inner1, inner2)
.flatMap(List::stream)
.collect(Collectors.toList())))
// list of combinations
.collect(Collectors.toList()))
// otherwise an empty list
.orElse(Collections.emptyList());
}
public static void main(String[] args) {
List<String> list1 = Arrays.asList("A", "B", "C");
List<String> list2 = Arrays.asList("W", "X", "Y", "Z");
List<String> list3 = Arrays.asList("L", "M", "K");
List<List<String>> lists = Arrays.asList(list1, list2, list3);
List<List<String>> combinations = combinations(lists);
// column-wise output
int rows = 6;
IntStream.range(0, rows).forEach(i -> System.out.println(
IntStream.range(0, combinations.size())
.filter(j -> j % rows == i)
.mapToObj(j -> combinations.get(j).toString())
.collect(Collectors.joining(" "))));
}
Column-wise output:
[A, W, L] [A, Y, L] [B, W, L] [B, Y, L] [C, W, L] [C, Y, L]
[A, W, M] [A, Y, M] [B, W, M] [B, Y, M] [C, W, M] [C, Y, M]
[A, W, K] [A, Y, K] [B, W, K] [B, Y, K] [C, W, K] [C, Y, K]
[A, X, L] [A, Z, L] [B, X, L] [B, Z, L] [C, X, L] [C, Z, L]
[A, X, M] [A, Z, M] [B, X, M] [B, Z, M] [C, X, M] [C, Z, M]
[A, X, K] [A, Z, K] [B, X, K] [B, Z, K] [C, X, K] [C, Z, K]
See also: Cartesian product of an arbitrary number of sets