La solution canonique est d'utiliser flatMap
. Cependant, la partie délicate consiste à créer l'objet Key
à partir des multiples niveaux d'entrée.
L'approche directe est de faire l'évaluation dans la fonction la plus interne, où chaque valeur est portée
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());
mais cela devient bientôt impossible avec l'imbrication profonde
Une solution sans imbrication profonde nécessite éléments pour contenir des valeurs de composés intermédiaires. Par exemple. si nous définissons Key
comme
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)+')';
}
}
(en supposant String
comme type d'élément), on peut utiliser
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());
Notez que ces flatMap
étapes sont maintenant au même niveau, à savoir non plus imbriqué. En outre, toutes ces étapes sont identiques, ne différant que dans le créateur réel, ce qui conduit à la solution générale supportant un nombre arbitraire de Creator
instances.
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());
Ici, chaque créateur est la cartographie à la fonction de production flux identique de la solution précédente, alors tous sont réduits à une fonction unique combinant chaque fonction avec une étape flatMap
à la suivante, et enfin la fonction résultante est exécuté pour obtenir un flux, qui est ensuite collecté à List
.
Lorsque vous avez besoin d'un nombre arbitraire de boucles, la récursivité est presque toujours la réponse. –