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());
}