2016-04-13 13 views
5

Ho a che fare con stream Java 8 e mi chiedo se potrei risolvere questo problema in modo elegante.Passaggio di oggetti attraverso flussi e mappe piatte

Questo è il mio scenario: Supponiamo di avere un elenco di parti e all'interno di ciascun elemento ho i nomi dei membri. Voglio scorrere l'elenco e crearne uno nuovo con i nomi e il partito a cui appartengono.

Il mio primo approccio è stato:

@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) { 

    } 

} 

Nel mio secondo approccio che ho cercato di usare le mappe operazioni di un flatmap:

@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()); 

} 

Il problema è che non riesco ad accedere all'oggetto partito all'interno del operazione della mappa. Quindi la domanda è di nuovo Posso fare in modo più funzionale? (come il secondo approccio)

Grazie!

+0

Sì, l'hack è di flatmap in un flusso di tupla, che conterrebbe il membro e il suo gruppo. Qualcosa come '.flatMap (party -> party.getMembers(). Stream(). Map (member -> new Tuple <> (party, member))'. E poiché non esiste una classe di tuple incorporata, è possibile il tuo o (ab) usa 'AbstractMap.SimpleEntry' ... – Tunaki

+0

Oppure' Pair.of (membro, membro) 'di commons-lang se hai già quella dipendenza. –

+2

@Tunaki: stai pensando troppo complicato ... – Holger

risposta

5

È scomposto troppo in singole operazioni:

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

Questo funziona spostando entrambi map passi nel flatMap fase, in cui solo il secondo sopravvive, ora applicato al “substream” restituito. Come indicato nei commenti della tua domanda, hai bisogno di una specie di tipo Pair per mappare gli elementi "substream", ma il tuo tipo Elector soddisfa esattamente questo, dato che è costruito usando i due valori che ti interessano. Quindi c'è non c'è bisogno di mappare a un Pair(member,party) generico solo per mappare a Elector in seguito.

2

per tenere tutto leggibile vorrei aggiungere un helper nella classe Party (o un metodo statico da qualche altra parte) per ottenere un Stream<Elector>:

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)); 
} 

E poi basta usare che nel vostro flatmap

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