Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing objects through streams and flatmaps

I'm dealing with Java 8 streams and I wondering if I could resolve this problem in a fancy way.

That's my scenario: Suppose I have a list of parties and inside each element I have the names of the members. I want to iterate over the list and make a new one with the names and which party they belong to.

My first approach was:

@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 my second approach I tried to use maps an flatmap's operations:

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

}

The problem is I can't access to the party object inside the map operation. So the question again is Can I do in a more functional way? (like the second approach)

Thanks!

like image 676
FedericoAlvarez Avatar asked Apr 13 '16 17:04

FedericoAlvarez


People also ask

How do you use flatMap in stream?

We can use a flatMap() method on a stream with the mapper function List::stream. On executing the stream terminal operation, each element of flatMap() provides a separate stream. In the final phase, the flatMap() method transforms all the streams into a new stream.

What is flat map () method does in stream?

The flatMap() method first flattens the input Stream of Streams to a Stream of Strings (for more about flattening, see this article).

What is difference between map () and flatMap () in java8?

The difference is that the map operation produces one output value for each input value, whereas the flatMap operation produces an arbitrary number (zero or more) values for each input value.


1 Answers

You decomposed too much into individual operations:

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

This works by moving both map steps into the flatMap step, where only the second one survives, now being applied to the returned “substream”. As pointed out in the comments of your question, you need some kind of Pair type to map the “substream” elements to, but your Elector type fulfills exactly that, as it is constructed using the two values you are interested in. So there is no need to map to a generic Pair(member,party) just to map to Elector afterwards.

like image 167
Holger Avatar answered Sep 18 '22 02:09

Holger