2016-04-13 12 views
5

Ich habe es mit Java 8 Streams zu tun, und ich frage mich, ob ich dieses Problem auf eine raffinierte Weise lösen könnte.Übergeben von Objekten durch Streams und Flatmaps

Das ist mein Szenario: Angenommen, ich habe eine Liste von Parteien und in jedem Element habe ich die Namen der Mitglieder. Ich möchte über die Liste iterieren und eine neue mit den Namen und der Partei erstellen, zu der sie gehören.

Mein erster Ansatz war:

@Test 
public void test(){ 

    Party firstParties = new Party("firstParty",Lists.newArrayList("Member 1","Member 2","Member 3")); 
    Party secondParty = new Party("secondParty",Lists.newArrayList("Member 4","Member 5","Member 6")); 

    List<Party> listOfParties = Lists.newArrayList(); 
    listOfParties.add(firstParty); 
    listOfParties.add(secondParty); 

    List<Elector> electors = new ArrayList<>(); 
    listOfParties.stream().forEach(party -> 
     party.getMembers().forEach(memberName -> 
      electors.add(new Elector(memberName,party.name)) 
     ) 
    ); 

} 

class Party { 
    List<String> members = Lists.newArrayList(); 
    String name = ""; 

    public Party(String name, List<String> members) { 
     this.members = members; 
     this.name = name; 
    } 

    public List<String> getMembers() { 
     return members; 
    } 
} 

class Elector{ 

    public Elector(String electorName,String partyName) { 

    } 

} 

In meinem zweiten Ansatz, den ich versuchte, ein flatmap Operationen zu verwenden Karten:

@Test 
public void test(){ 

    Party firstParty = new Party("firstParty",Lists.newArrayList("Member 1","Member 2","Member 3")); 
    Party secondParty = new Party("secondParty",Lists.newArrayList("Member 4","Member 5","Member 6")); 

    List<Party> listOfParties = Lists.newArrayList(); 
    listOfParties.add(firstParty); 
    listOfParties.add(secondParty); 

    List<Elector> people = listOfParties.stream().map(party -> party.getMembers()) 
      .flatMap(members -> members.stream()) 
      .map(membersName -> new Elector(membersName, party.name)) #Here is my problem variable map doesn't exist 
      .collect(Collectors.toList()); 

} 

Das Problem ist, ich nicht auf das Party-Objekt in dem Zugriff auf Kartenoperation. Die Frage ist also wieder Kann ich es auf eine funktionellere Weise tun? (wie der zweite Ansatz)

Vielen Dank!

+0

Ja, der Hack soll in einen Stream von Tupel flammap, die das Mitglied und seine Partei enthalten würde. Etwas wie '.flatMap (party -> party.getMembers(). Stream(). Map (Mitglied -> neues Tupel <> (Partei, Mitglied))'. Und da es keine eingebaute Tuple-Klasse gibt, können Sie machen eigene oder (ab) verwenden 'AbstractMap.SimpleEntry' ... – Tunaki

+0

Oder' Pair.of (Partei, Mitglied) 'aus commons-lang, wenn Sie bereits diese Abhängigkeit haben. –

+2

@Tunaki: Sie denken zu kompliziert ... – Holger

Antwort

5

Sie zu viel zerlegt in einzelne Operationen:

List<Elector> people = listOfParties.stream() 
    .flatMap(party -> party.getMembers().stream() 
     .map(membersName -> new Elector(membersName, party.name))) 
    .collect(Collectors.toList()); 

Dies funktioniert, indem beide map Schritte in den flatMap Schritt, in dem nur der zweite jetzt überlebt, zu dem zurückgegebenen „Teil“ angewendet wird. Wie in den Kommentaren Ihrer Frage erwähnt, benötigen Sie eine Art von Pair Typ, um die "substream" -Elemente zuzuordnen, aber Ihr Elector Typ erfüllt genau das, da es mit den zwei Werten erstellt wird, die Sie interessieren. So ist es Keine Notwendigkeit, zu einem generischen Pair(member,party) zuzuordnen, nur um danach zu Elector zu mappen.

2

Um alles lesbar halten würde ich eine Hilfsmethode in der Party Klasse hinzufügen (oder eine statische Methode woanders) ein Stream<Elector> zu bekommen:

public Stream<Elector> electors() { 
    return getMembers().stream().map(member -> new Elector(member, name)); 
} 
// Alternatively 
public static Stream<Elector> electors(final Party p) { 
    return p.getMembers().stream().map(member -> new Elector(member, p.name)); 
} 

Und dann nur verwenden, die in Ihrem flatmap

final List<Elector> people = listOfParties.stream() 
    .flatMap(Party::electors) 
    .collect(Collectors.toList()); 
Verwandte Themen