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!
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.
The flatMap() method first flattens the input Stream of Streams to a Stream of Strings (for more about flattening, see this article).
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With