规范的解决方案是使用flatMap。然而,棘手的部分是从多个输入级别创建Key 对象。
直接的方法是在最里面的函数中进行评估,其中每个值都在范围内
final List<Key> keys = firstElementCreator.getApplicableElements().stream()
.flatMap(first -> secondElementCreator.getApplicableElements().stream()
.flatMap(second -> thirdElementCreator.getApplicableElements().stream()
// ... more creators
.map( X -> new Key( first, second, third, ..., X ) ) ) )
.collect(Collectors.toList());
但这很快就会因为深度嵌套而变得不切实际
没有深度嵌套的解决方案需要元素来保存中间复合值。例如。如果我们将Key 定义为
class Key {
String[] data;
Key(String... arg) {
data=arg;
}
public Key add(String next) {
int pos = data.length;
String[] newData=Arrays.copyOf(data, pos+1);
newData[pos]=next;
return new Key(newData);
}
@Override
public String toString() {
return "Key("+Arrays.toString(data)+')';
}
}
(假设String为元素类型),我们可以使用
final List<Key> keys =
firstElementCreator.getApplicableElements().stream().map(Key::new)
.flatMap(e -> secondElementCreator.getApplicableElements().stream().map(e::add))
.flatMap(e -> thirdElementCreator.getApplicableElements().stream().map(e::add))
// ... more creators
.collect(Collectors.toList());
请注意,这些 flatMap 步骤现在位于同一级别,即不再嵌套。此外,所有这些步骤都是相同的,只是实际创建者不同,这导致通用解决方案支持任意数量的Creator 实例。
List<Key> keys = Stream.of(firstElementCreator, secondElementCreator, thirdElementCreator
/* , and, some, more, if you like */)
.map(creator -> (Function<Key,Stream<Key>>)
key -> creator.getApplicableElements().stream().map(key::add))
.reduce(Stream::of, (f1,f2) -> key -> f1.apply(key).flatMap(f2))
.apply(new Key())
.collect(Collectors.toList());
在这里,每个创建者都映射到与前一个解决方案相同的流生成函数,然后将所有函数都简化为一个函数,将每个函数与flatMap 步骤组合到下一个,最后执行生成的函数获取流,然后将其收集到List。