2017-02-20 4 views
2

Ich habe eine Artist Klasse wie folgt:Verwendung von flatMap() in Java8

class Artist { 
    private final String name; 
    private final String origin; 
    private Stream<Artist> members; 

    public Artist(String name, String origin) { 
     this.name = name; 
     this.origin = origin; 
     this.members = null; 
    } 

    public Artist(String name, String origin,Stream<Artist> members) { 
      this.name = name; 
      this.origin = origin; 
      this.members = members; 
    } 

    public String getName() { 
      return name; 
    } 

    public String getOrigin() { 
     return origin; 
    } 

    public Stream<Artist> getMembers() { 
     return members; 
    } 

    @Override 
    public String toString() { 
     return name; 
    } 
} 

Nun erstellen wir eine Liste von Künstlern, in denen der Name des Künstlers ist ein Band oder eine einzelne Einheit. Für einzelne Entität "members" Attribut bleibt null.Now die Liste ist wie folgt:

List<Artist> artists = Arrays.asList(
       new Artist("Fossils","Kolkata", Stream.of(new Artist("Rupam Islam","Kolkata"), new Artist("Deep","Kolkata"),new Artist("Allan","Kolkata"), new Artist("Chandramouli","Kolkata"),new Artist("Tanmoy","Kolkata"))), 
       new Artist("Linkin Park","California",Stream.of(new Artist("Chester Bennington","California"),new Artist("Dave Farrell","California"), new Artist("Mike Shinoda","California"),new Artist("Rob Bourdon","California"),new Artist("Brad Delson","California"))), 
       new Artist("Cactus","Kolkata",Stream.of(new Artist("Sidhartha Sankar","Kolkata"),new Artist("Dibyendu Mukherjee","Kolkata"), new Artist("Ritaprabha","Kolkata"),new Artist("Sudipto","Kolkata"),new Artist("Mainak","Kolkata"))), 
       new Artist("Backstreet Boys","Florida",Stream.of(new Artist("A. J. McLean","Florida"),new Artist("Howie D.","Florida"),new Artist("Nick Carter","Florida"), new Artist("Kevin Richardson","Florida"), new Artist("Brian Littrell","Florida"))), 
       new Artist("Prohori","Kolkata",Stream.of(new Artist("Pritam","Kolkata")))); 

Wir nicht von einzelnen Unternehmen haben wollen, von „Kolkata“. Verwendung externer Iteration können wir folgende Lösung haben:

int totalMembers = 0; 
for (Artist artist : artists) { 
    if(artist.getOrigin().equals("Kolkata") { 
     Stream<Artist> members = artist.getMembers(); 
     totalMembers += members.count(); 
    } 
} 

Was wird die Lösung für die interne Iteration mit stream() und flatMap() mit Hilfe von Lambda-Expression?

Ich habe an eine Lösung gedacht, aber möglicherweise ist es falsch.

int totalMember = artists.stream() 
         .filter(d -> d.getOrigin().equals("Kolkata")) 
         .flatMap(e -> e.getMembers()) 
         .map(f -> 1).reduce(0, (a, b) -> a + b); 
+0

große Sache, warum es falsch ist, dass Sie ein Feld vom Typ 'Strom haben '. Streams können nur einmal verwendet werden. Wenn Sie Ihren Code zweimal hintereinander aufrufen, erhalten Sie eine Ausnahme. Abgesehen davon, kann Ihre Lösung durch die Verwendung von geeigneten Builtins (wie das Zählen von Sammler) verbessert werden, aber insgesamt ist in Ordnung. –

+1

@SoumyaKantiNaskar ein bisschen unklar .. wollen Sie die Gesamtzahl der Künstler aus einer bestimmten Region, wo 'Mitglieder' null ist? Nehme dein Beispiel: 'neuer Künstler (" Fossils "," Kolkata ", Stream.of (neuer Künstler (" Rupam Islam "," Kolkata "), neuer Künstler (" Deep "," Kolkata "), neuer Künstler (" Allan "," Kolkata "), neuer Künstler (" Chandramouli "," Kolkata "), neuer Künstler (" Tanmoy "," Kolkata "))). Sollte dies Null oder 5 ergeben? Sie möchten die inneren Künstler auch zählen? – Eugene

+1

@SoumyaKantiNaskar Ihr Beispiel der 'externen Iteration' (neben der Möglichkeit, eine NullPointerException zu werfen, weil Mitglieder null sein könnten), erfüllt auch nicht Ihre eigenen Anforderungen:' Wir wollen keine einzige Entität haben', wobei 'Für einzelne Entität ' Mitglieder "Attribut bleibt null". – Eugene

Antwort

3

Ihre externe Schleife zählt die Anzahl der Mitglieder, die das Band von Kolkata haben. wenn Sie wirklich wollen, dass:

long result = artists.stream().filter(a -> a.getOrigin().equals("Kolkata")) 
      .filter(a -> a.getMembers() != null) 
      .flatMap(a -> a.getMembers()) 
      .count(); 
+0

Ihre erste Lösung gibt das Ergebnis 0 –

+1

@SoumyaKantiNaskar für Ihr Beispiel Was ist die Lust Ausgabe 11? Wenn ja, dann zählt das zweite Beispiel diese inneren Mitglieder – Eugene

+0

Diese Lösung gibt mir einen Fehler: java.lang.IllegalStateException: Strom wurde bereits betrieben oder geschlossen –

0

Summe der Zählungen der Ströme in einem LongStream:

long totalMember = artists.stream() 
          .filter(d -> d.getOrigin().equals("Kolkata")) 
          .map(Artist::getMembers) 
          .filter(m -> m != null) 
          .mapToInt(Stream::count) 
          .sum(); 
+0

'Für einzelne Entität" Mitglieder "Attribut bleibt null '. Es scheint, als ob es mindestens einen anderen Filter geben sollte. – Eugene

+0

@eugene OK ... hinzugefügt nicht null Filter – Bohemian

+0

Ich bin mir nicht sicher, was das OP eigentlich zählen will .. Er sagt 'Wir wollen keine einzelne Entität von" Kolkata "haben, aber seine externe Schleife zählt die tatsächlichen Mitglieder (So ​​wie du es gemacht hast). – Eugene

1

Ihre Lösung wird die erwartete Ausgabe d.h geben. Sie können auch verwenden:

int totalMembers = (int) artists.stream() 
           .flatMap(d->d.getMembers()) 
           .filter(d->d.getOrigin().equals("Kolkata")) 
           .count(); 

Unterschied zwischen den beiden Lösungen ist, ich habe flattened die Liste vor filtering es und verwendet long count(); statt reduce(). Was später Lösung ist, es überprüft die origin von Stream<Artist> members und nicht die origin von artists. Ich hoffe das hilft. Ich würde mich freuen, wenn jemand die optimierte Lösung diskutieren kann.

+0

Ihre Lösung gibt einen Fehler Ausnahme im Thread "Main" java.lang.IllegalStateException: Stream wurde bereits bearbeitet oder geschlossen –

+0

Ich weiß nicht, warum es Ihnen IllegalStateException gibt, denn es scheint für mich gut zu funktionieren. Können Sie den Code kopieren und einfügen und dann versuchen. –

+0

Meine schlechte .. Es funktioniert gut. Aber wir müssen zuerst den Filter() verwenden. Es wird einen Teil des Overheads reduzieren, da wir die "Bänder" ausgefiltert haben. –

0

prüfen auch diese Lösung. Es kann auch passieren, dass ein Bandmitglied eine Bande einer bestimmten Lokalität bildet, die nicht von derselben Lokalität stammt. So wird die exakte Lösung sein:

long totalMember = artists.stream().filter(a -> a.getOrigin().equals("Kolkata")) 
          .flatMap(a -> a.getMembers()) 
          .filter(a -> a.getOrigin().equals("Kolkata")) 
          .count();