Ich habe eine Liste von names und eine Liste von versions. Ich möchte alle Permutationen erhalten, die durch Verketten der Zeichenfolge aus zwei Listen erstellt werden. Ich verwende zwei for-Schleifen, um dies zu tun, aber ich möchte zu einem funktionaleren Stil wechseln. Hier ist meine Lösung:

List<String> names = new ArrayList<>();
List<String> versions = new ArrayList<>();
List<String> result = new ArrayList<>();
names.forEach(name -> versions.stream().map(version -> result.add(name.concat(version))));

Gibt es einen besseren Weg, dies zu tun?

1
dashenswen 7 Feb. 2020 im 21:41

3 Antworten

Beste Antwort

Sie suchen das "kartesische Produkt" von names und versions - im Grunde das Rückgabeset / die Rückgabeliste aus den oben genannten Sätzen / Listen.

final Stream<List<String>> result = names.stream()
    .flatMap(s1 -> versions.stream().flatMap(s2 -> Stream.of(Arrays.asList(s1, s2))));
result.forEach(System.out::println);

Denken Sie daran, dass der Betrieb sehr teuer ist. Googles Guave hat dies auch unter com.google.common.collect.Sets.cartesianProduct(s1, s2) implementiert.

2
x80486 7 Feb. 2020 im 18:51

Oder etwas aufgeräumter:

final List<String> result = names.stream()          // Stream the Names...
        .flatMap(name    -> versions.stream()       // ...together with Versions.
        .map    (version -> name.concat(version)))  // Combine Name+Version
        .collect(Collectors.toList());              // & collect in List.
0
Dave The Dane 7 Feb. 2020 im 19:39

Sie sollten sich darauf freuen, flatMap zu verwenden, während Sie über names streamen und dann die map - Operation weiter korrekt ausführen:

List<String> result = names.stream() // for each name
        .flatMap(name -> versions.stream() // for each version
                .map(version -> name.concat(version))) // concat version to the name
        .collect(Collectors.toList()); // collect all such names
1
Naman 7 Feb. 2020 im 19:16