如何用Java 8流替换嵌套循环

时间:2017-02-27 18:26:00

标签: java java-8 java-stream

我想将Java 8流用于以下实现。基本上我想解析一个列表并形成另一个不同对象的列表。

输入 - 人物pojos列表, 输出 - PersonInfo pojos列表

    List<Person> persons = new ArrayList<Person>();

    Person max = new Person();
    max.setName("Max");
    max.setAge(10);
    max.addAddress(new Address("Street1", "City1"));
    max.addAddress(new Address("Street2", "City2"));

    Person peter = new Person();
    peter.setName("Peter");
    peter.setAge(20);
    peter.addAddress(new Address("Street1", "City1"));
    peter.addAddress(new Address("Street2", "City2"));

    persons.add(max);
    persons.add(peter);

    System.out.println("Input: " + persons);

    List<PersonInfo> personInfos = new ArrayList<PersonInfo>();
    PersonInfo personInfo = null;
    for (Person person : persons) {
        for (Address addr : person.getCurrAndPrevAddrs()) {
            personInfo = new PersonInfo();
            personInfo.setName(person.getName());
            personInfo.setAge(person.getAge());
            personInfo.setAddrs(addr);              
            personInfos.add(personInfo);
        }
    }

    System.out.println("Output: " + personInfos.toString());

示例输出输入:[最多10 [Street1 City1,Street2 City2]

,Peter 20 [Street1 City1,Street2 City2]]

输出:[Max 10 Street1 City1

,Max 10 Street2 City2

,Peter 20 Street1 City1

,Peter 20 Street2 City2]

3 个答案:

答案 0 :(得分:4)

List<PersonInfo> personInfos = persons.stream().flatMap(person -> person.getCurrAndPrevAddrs().stream().map(addr -> {
        PersonInfo personInfo = new PersonInfo();
        personInfo.setName(person.getName());
        personInfo.setAge(person.getAge());
        personInfo.setAddrs(addr);              
        return personInfo;
})).collect(Collectors.toList());

答案 1 :(得分:2)

以下是您尝试执行的操作的简化版本。我为我的测试简化了Pojos。

List<Person> persons = new ArrayList<Person>();

Person person1 = new Person("person1");
Person person2 = new Person("person2");

persons.add(person1);
persons.add(person2);

List<PersonInfo> personInfos = new ArrayList<PersonInfo>();
persons.stream().forEach(person -> {    
  person.getCurrAndPrevAddrs().stream().forEach(address -> {
    PersonInfo personInfo = new PersonInfo("personInfo");
    personInfo.setAddress(address);
    personInfos.add(personInfo);
  });
});

System.out.println("Output: " + personInfos.toString());

答案 2 :(得分:1)

(1)提高可读性和(2)简化代码维护的一种方法是向toPersonInfo类添加Person方法,如下所示:

public class Person {
    //getters, setters, etc.
    public List<PersonInfo> toPersonInfos() {
        List<PersonInfo> result = new ArrayList<>();
        for (Address addr : getCurrentAndPrevAddrs()) {
            PersonInfo pi = new PersonInfo();
            pi.setName(this::getName);
            pi.setAge(this::getAge);
            pi.setAddrs(this::addr);
            result.add(pi);
        }
        return result;
    }
}

这样,如果您更改了PersonInfoPerson课程,则只需更改一种方法,它就在您的Person课程中。

它还极大地简化了流操作:

personInfos = persons.stream().flatMap(p -> p.toPersonInfos.stream()).collect(Collectors.toList());

请注意,这不一定会返回有序列表。