2016-04-13 1 views
5

Я имею дело с потоками 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) { 

    } 

} 

На втором подходе я пытался использовать карты операции, которые 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()); 

} 

Проблема в том, что я не могу получить доступ к объекту партии внутри операции с картами. Итак, вопрос снова: могу ли я сделать более функциональный способ? (например, второй подход)

Спасибо!

+0

Да, взлом - это плоская карта в поток кортежа, в который будет входить член и его сторона. Что-то вроде '.flatMap (party -> party.getMembers(). Stream(). Map (member -> new Tuple <> (party, member)). И поскольку нет встроенного кортежа, вы можете сделать ваш собственный или (ab) использовать 'AbstractMap.SimpleEntry' ... – Tunaki

+0

Или' Pair.of (party, member) 'из commons-lang, если у вас уже есть эта зависимость. –

+2

@Tunaki: вы думаете слишком сложно ... – Holger

ответ

5

Вы разлагаетесь слишком много на отдельные операции:

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 впоследствии.

2

Чтобы сохранить все читаемый Я хотел бы добавить вспомогательный метод в 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()); 
Смежные вопросы