2017-02-27 68 views
4

我想为下面的实现使用Java 8流。基本上我想解析一个列表并形成不同对象的另一个列表。如何用Java 8流代替嵌套循环

输入 - 人的POJO列表, 输出 - PersonInfo的POJO列表

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城2]

,彼得20 Street1 City1,STREET2城2]]

输出:[最大10 Street1 City1

,最多10 STREET2城2

,彼得20 Street1 City1

,彼得20 STREET2城2]

+0

输出:输入:?? –

+0

@Elise van Looij,我提供了关于我的问题的示例输出和输入。如果您需要更多信息,请告诉我。 – Pons

回答

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()); 
+0

我收到一些编译错误。 1.'persons.flatMap',“人”是列表或流,我想你的意思是说'persons.stream()flatMap' 2“类型不匹配:不能从流转换到列表”。 – Pons

+1

@Pons我在我的手机上,所以我很难验证。你可以说得更详细点吗? – shmosel

+1

@Pons你说得对第一点。我也错过了一个括号。现在试试。 – shmosel

2

下面是一个简化你正在尝试做什么的版本。我简化了Pojos的测试。 (1)提高可读性和(2)简化代码的维护

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()); 
+0

谢谢,这工作正常。但有一点是,'forEach'可用于'Iterable',所以,我试图让我的头脑发现,这会给我带来什么样的好处? – Pons

+0

这看起来像它会在并行实现上抛出一个ConcurrentModificationException异常。 – MikaelF

1

一种方式是一个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; 
    } 
} 

这样,如果你更改过自己的PersonInfo或您的Person类,你只需要改变一个方法,这是正确的,在你的Person类。

这也大大简化了流操作:

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

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