Reputation: 1111
I want to use Java 8 stream for the below implementation. Basically i want to parse one list and form another list of different objects.
Input - list of Person pojos, Output - list of 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());
sample output: Input: [Max 10 [Street1 City1, Street2 City2]
, Peter 20 [Street1 City1, Street2 City2]]
Output: [Max 10 Street1 City1
, Max 10 Street2 City2
, Peter 20 Street1 City1
, Peter 20 Street2 City2]
Upvotes: 5
Views: 12795
Reputation: 1
A cleaner and elegant way to do this could be :
List<PersonInfo> personInfos = persons.stream()
.map(person -> person.getCurrAndPrevAddrs())
.flatMap(List::stream)
.map(this::createPersonInfo)
.collect(Collectors.toList());
private PersonInfo createPersonInfo() {
PersonInfo personInfo = new PersonInfo();
personInfo.setName(person.getName());
personInfo.setAge(person.getAge());
personInfo.setAddrs(addr);
return personInfo;
}
Upvotes: -1
Reputation: 3664
One way to (1) improve readability and (2) simplify maintenance of your code is to add a toPersonInfo
method to your Person
class, like so:
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;
}
}
That way, if you ever change your PersonInfo
or your Person
class, you only have to change one method, and it's right there in your Person
class.
It also greatly simplifies the stream operation:
personInfos = persons.stream().flatMap(p -> p.toPersonInfos.stream()).collect(Collectors.toList());
Note that this will not necessarily return an ordered list.
Upvotes: 1
Reputation: 50776
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());
Upvotes: 5
Reputation: 1296
Here is a simplified version of what you're trying to do. I simplified the Pojos for my testing.
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());
Upvotes: 3