I have classes Employee and Address as follows:
public static class Employee {
private List<Address> address;
// getters, etc.
}
public static class Address {
private String city;
// getters, etc.
}
I am learning streams, I am trying to iterate over the objects from list of list and create a set of unique values. I was able to get it working by using nested for loop. How can I convert below code to streams?
public static Set<String> getCityUniquName(List<Employee> emp){
Set<String> cityUniquName = new HashSet<>();
for(Employee e: emp){
List<Address> addList = e.getAddress();
for(Address add: addList){
cityUniquName.add(add.getCity());
}
}
return cityUniquName;
}
CodePudding user response:
Use flatMap to flatten the Address list and then use map to get the city from each Address object and then collect into Set
Set<String> cityUniquName = emp.stream()
.flatMap(Employee::getAddress)
.map(Address::getCity)
.collect(Collectors.toSet());
CodePudding user response:
Since each Employee is associated with a collection of Address instances, you need to apply of the stream operations that allow to flatten the data, namely either flatMap(), or mapMulty().
Note that flatMap() expects a function producing a Stream,not a Collection like shown in another answer.
Stream.flatMap
To turn a Stream of Employee into a Stream of Address in the mapper function of flatMap() we need to extract the collection of addresses and create a stream over it.
The only thing left is to get the city name and collect the result into a set.
public static Set<String> getCityUniqueName(List<Employee> emp) {
return emp.stream()
.flatMap(e -> e.getAddress().stream())
.map(Address::getCity)
.collect(Collectors.toSet());
}
Stream.mapMulti
mapMulti() expects a BiConsumer, which in turn takes two arguments: stream element (having an initial type) and a Consumer of the resulting type. Every object offered to the consumer would appear in the resulting stream.
public static Set<String> getCityUniqueName1(List<Employee> emp) {
return emp.stream()
.<Address>mapMulti((e, c) -> e.getAddress().forEach(c))
.map(Address::getCity)
.collect(Collectors.toSet());
}
