通过流和 flatmap 传递对象

6

我正在处理Java 8流,想知道是否可以用一种花哨的方法解决这个问题。

这是我的场景: 假设我有一个政党列表,每个元素里面都有成员的姓名。我想遍历列表并创建一个新的列表,其中包含名字和他们所属的政党。

我的第一种方法是:

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

    }

}

在我的第二个尝试中,我尝试使用maps和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());

}

问题是我无法在map操作中访问party对象。所以问题又来了能否以更加函数式的方式实现呢?(比如第二种方法)
谢谢!

是的,技巧是将其扁平化为一个元组流,其中包含成员和所属党派。就像这样:.flatMap(party -> party.getMembers().stream().map(member -> new Tuple<>(party, member))。由于没有内建的元组类,你可以自己创建一个或(滥用)使用AbstractMap.SimpleEntry... - Tunaki
如果您已经有该依赖项,则可以使用commons-lang中的Pair.of(party, member) - Jean-François Savard
2
@Tunaki:你在想得太复杂了... - Holger
2个回答

11

您将太多内容分解为单独的操作:

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

这个方法是通过将两个map步骤移动到flatMap步骤中,只有第二个步骤生效,现在被应用于返回的“子流”。如评论中指出的那样,您需要某种Pair类型来将“子流”元素映射为,但您的Elector类型完全满足此要求,因为它使用您感兴趣的两个值构造。因此,没有必要先映射到通用的Pair(member,party),然后再映射到Elector


阅读 https://dev59.com/L18d5IYBdhLWcg3wkS0V#26684710 澄清了这里发生了什么。 - ccpizza

3
为了保持可读性,我建议在Party类中(或其他地方的静态方法中)添加一个帮助方法来获取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));
}

然后在您的flatmap中使用它。
final List<Elector> people = listOfParties.stream()
    .flatMap(Party::electors)
    .collect(Collectors.toList());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接